/*
 * IRC - Internet Relay Chat, ircd/ircd_snprintf.c
 * Copyright (C) 2000 Kevin L. Mitchell <klmitch@mit.edu>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
/** @file
 * @brief IRC-specific printf() clone implementation.
 * @version $Id: ircd_snprintf.c 2532 2009-07-29 01:10:44Z sirvulcan $
 */
#include "config.h"

#include "client.h"
#include "channel.h"
#include "ircd_log.h"
#include "ircd_snprintf.h"
#include "ircd_struct.h"

/* #include <assert.h> -- Now using assert in ircd_log.h */
#include <errno.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

/* Inhibit complaints when we use GCC extensions */
#if defined(__GNUC__) && SIZEOF_LONG_LONG
# define EXTENSION __extension__
#else
/** Fallback (empty) definition of EXTENSION. */
# define EXTENSION
#endif

/* Find the largest type */
#if SIZEOF_LONG_LONG
EXTENSION typedef long long _large_t;
EXTENSION typedef unsigned long long _ularge_t;
# define SIZEOF__LARGE_T SIZEOF_LONG_LONG
/* Oh, if long long happens to be the size of void *, set _pointer_t, too */
# if SIZEOF_LONG_LONG == SIZEOF_VOID_P
typedef _ularge_t _pointer_t;
#  define HAVE_POINTER_T
# endif
#else
/** Fallback definition of the largest integer type. */
typedef long _large_t;
/** Fallback definition of the largest unsigned integer type. */
typedef unsigned long _ularge_t;
/** Fallback definition of SIZEOF__LARGE_T. */
# define SIZEOF__LARGE_T SIZEOF_LONG
#endif

/* Select something for _pointer_t */
#ifndef HAVE_POINTER_T
# if SIZEOF_LONG == SIZEOF_VOID_P
/** Unsigned integer type large enough to hold a pointer. */
typedef unsigned long _pointer_t;
# elif SIZEOF_INT == SIZEOF_VOID_P
typedef unsigned int _pointer_t;
# else
#  error Unable to find a suitable type for _pointer_t
# endif
#endif /* HAVE_POINTER_T */

/** rough length sufficient to hold an octal number, since those can be large */
#define INTBUF_LEN (SIZEOF__LARGE_T * 3)

/** Return minimum of \a i1 and \a i2. */
#define SNP_MIN(i1, i2)	((i1) < (i2) ? (i1) : (i2))
/** Return maximum of \a i1 and \a i2. */
#define SNP_MAX(i1, i2)	((i1) > (i2) ? (i1) : (i2))
/** Indicate total number of bytes "pseudo-output" in buffer. */
#define TOTAL(buf_p)	((buf_p)->buf_loc + \
			 SNP_MAX((buf_p)->buf_overflow, (buf_p)->overflow))

#define WIDTH_MAX	999	/**< keep from overflowing width */

/** data about the output buffer */
struct BufData {
  char	       *buf;		/**< pointer to buffer */
  size_t	buf_size;	/**< maximum size of buffer */
  size_t	buf_overflow;	/**< how much buffer has been overflowed */
  size_t	buf_loc;	/**< where we are in the buffer */
  short		limit;		/**< max # of chars to convert */
  size_t	overflow;	/**< how much we overflowed the limit */
};

/** initializer for BufData */
#define BUFDATA_INIT	{ 0, 0, 0, 0, 0, 0 }

/** data about format fields */
struct FieldData {
  unsigned int	flags;		/**< flags describing argument */
  short		base;		/**< base for integer conversions */
  short		width;		/**< width of field */
  short		prec;		/**< precision of field */
  union {
    _ularge_t	v_int;		/**< an integer value */
    long double	v_float;	/**< a floating point value -- NOT SUPPORTED */
    void       *v_ptr;		/**< a pointer value */
  }		value;		/**< value of a field */
};

/** initializer for FieldData */
#define FIELDDATA_INIT	{ 0, 0, 0, 0, { 0 } }

/* Specifier flags */
#define FLAG_MINUS	0x00000001	/**< found a '-' flag */
#define FLAG_PLUS	0x00000002	/**< found a '+' flag */
#define FLAG_SPACE	0x00000004	/**< found a ' ' flag */
#define FLAG_ALT	0x00000008	/**< found a '#' flag */
#define FLAG_ZERO	0x00000010	/**< found a '0' flag */
#define FLAG_COLON	0x00000020	/**< found a ':' flag */

#define FLAG_RESERVED1	0x00000040	/**< reserved for future expansion */
#define FLAG_RESERVED0	0x00000080	/**< reserved for future expansion */

/* integer types */
#define TYPE_CHAR	0x00000100	/**< number is a char */
#define TYPE_SHORT	0x00000200	/**< number is a short */
#define TYPE_LONG	0x00000400	/**< number is a long */
#define TYPE_QUAD	0x00000800	/**< number is a quad */

/* special integer types */
#define TYPE_INTMAX	0x00001000	/**< number is an intmax_t */
#define TYPE_PTRDIFF	0x00002000	/**< number is a ptrdiff_t */
#define TYPE_SIZE	0x00004000	/**< number is a size_t */
#define TYPE_TIME	0x00008000	/**< number is a time_t */
#define TYPE_POINTER	0x00010000	/**< number is a pointer_t */

/* floating point types */
#define TYPE_LONGDOUBLE	0x00020000	/**< number is a long double */

#define TYPE_RESERVED1	0x00040000	/**< reserved for future expansion */
#define TYPE_RESERVED0	0x00080000	/**< reserved for future expansion */

/** Mask to get just the type data */
#define TYPE_MASK	(TYPE_CHAR | TYPE_SHORT | TYPE_LONG | TYPE_QUAD | \
			 TYPE_INTMAX | TYPE_PTRDIFF | TYPE_SIZE | TYPE_TIME | \
			 TYPE_POINTER | TYPE_LONGDOUBLE)

/* type of argument to extract */
#define ARG_INT		0x00100000	/**< argument is an integer */
#define ARG_FLOAT	0x00200000	/**< argument is a float */
#define ARG_PTR		0x00300000	/**< argument is a pointer */

#define ARG_RESERVED11	0x00400000	/**< reserved for future expansion */
#define ARG_RESERVED10	0x00500000	/**< reserved for future expansion */
#define ARG_RESERVED9	0x00600000	/**< reserved for future expansion */
#define ARG_RESERVED8	0x00700000	/**< reserved for future expansion */
#define ARG_RESERVED7	0x00800000	/**< reserved for future expansion */
#define ARG_RESERVED6	0x00900000	/**< reserved for future expansion */
#define ARG_RESERVED5	0x00a00000	/**< reserved for future expansion */
#define ARG_RESERVED4	0x00b00000	/**< reserved for future expansion */
#define ARG_RESERVED3	0x00c00000	/**< reserved for future expansion */
#define ARG_RESERVED2	0x00d00000	/**< reserved for future expansion */
#define ARG_RESERVED1	0x00e00000	/**< reserved for future expansion */
#define ARG_RESERVED0	0x00f00000	/**< reserved for future expansion */

/* Mask to get just the argument data */
#define ARG_MASK	0x00f00000      /**< masks off non-argument bits */

/* type of conversion to perform */
#define CONV_INT	0x01000000	/**< convert integers */
#define CONV_FLOAT	0x02000000	/**< convert floats */
#define CONV_CHAR	0x03000000	/**< convert chars */
#define CONV_STRING	0x04000000	/**< convert strings */
#define CONV_VARARGS	0x05000000	/**< convert a %v */
#define CONV_CLIENT	0x06000000	/**< convert a struct Client */
#define CONV_CHANNEL	0x07000000	/**< convert a struct Channel */
#define CONV_REAL	0x08000000      /**< convert a struct Client and show realhost */

#define CONV_RESERVED6	0x09000000	/**< reserved for future expansion */
#define CONV_RESERVED5	0x0a000000	/**< reserved for future expansion */
#define CONV_RESERVED4	0x0b000000	/**< reserved for future expansion */
#define CONV_RESERVED3	0x0c000000	/**< reserved for future expansion */
#define CONV_RESERVED2	0x0d000000	/**< reserved for future expansion */
#define CONV_RESERVED1	0x0e000000	/**< reserved for future expansion */
#define CONV_RESERVED0	0x0f000000	/**< reserved for future expansion */

/* Mask to get just the conversion data */
#define CONV_MASK	0x0f000000      /**< masks off non-conversion bits */

/* Value information flags */
#define INFO_RESERVED0	0x10000000	/**< reserved for future expansion */
#define INFO_UPPERCASE	0x20000000	/**< use uppercase characters */
#define INFO_UNSIGNED	0x40000000	/**< number is unsigned */
#define INFO_NEGATIVE	0x80000000	/**< number is negative */

#define BASE_OCTAL	9	/**< octal base; bits-per-char * 3 */
#define BASE_DECIMAL	-1000	/**< decimal base; 10 ** 3 */
#define BASE_HEX	12	/**< hexadecimal base; bits-per-char * 3 */


/* padding...			 1	   2	     3	       4	 5 */
/*			12345678901234567890123456789012345678901234567890 */
/** Predefined space padding. */
static char spaces[] = "                                                  ";
/** Predefined zero padding. */
static char zeros[]  = "00000000000000000000000000000000000000000000000000";

/** Length of predefined padding strings. */
#define PAD_LENGTH	(sizeof(spaces) - 1)

/*
 * Note that these string tables have characters reversed.  There is, of
 * course, a reason for this; check out how they're built in doprintf.
 */

/** string table for octal values */
static char *octal[] = {
     "",   "1",   "2",   "3",   "4",   "5",   "6",   "7",
   "01",  "11",  "21",  "31",  "41",  "51",  "61",  "71",
   "02",  "12",  "22",  "32",  "42",  "52",  "62",  "72",
   "03",  "13",  "23",  "33",  "43",  "53",  "63",  "73",
   "04",  "14",  "24",  "34",  "44",  "54",  "64",  "74",
   "05",  "15",  "25",  "35",  "45",  "55",  "65",  "75",
   "06",  "16",  "26",  "36",  "46",  "56",  "66",  "76",
   "07",  "17",  "27",  "37",  "47",  "57",  "67",  "77",
  "001", "101", "201", "301", "401", "501", "601", "701",
  "011", "111", "211", "311", "411", "511", "611", "711",
  "021", "121", "221", "321", "421", "521", "621", "721",
  "031", "131", "231", "331", "431", "531", "631", "731",
  "041", "141", "241", "341", "441", "541", "641", "741",
  "051", "151", "251", "351", "451", "551", "651", "751",
  "061", "161", "261", "361", "461", "561", "661", "761",
  "071", "171", "271", "371", "471", "571", "671", "771",
  "002", "102", "202", "302", "402", "502", "602", "702",
  "012", "112", "212", "312", "412", "512", "612", "712",
  "022", "122", "222", "322", "422", "522", "622", "722",
  "032", "132", "232", "332", "432", "532", "632", "732",
  "042", "142", "242", "342", "442", "542", "642", "742",
  "052", "152", "252", "352", "452", "552", "652", "752",
  "062", "162", "262", "362", "462", "562", "662", "762",
  "072", "172", "272", "372", "472", "572", "672", "772",
  "003", "103", "203", "303", "403", "503", "603", "703",
  "013", "113", "213", "313", "413", "513", "613", "713",
  "023", "123", "223", "323", "423", "523", "623", "723",
  "033", "133", "233", "333", "433", "533", "633", "733",
  "043", "143", "243", "343", "443", "543", "643", "743",
  "053", "153", "253", "353", "453", "553", "653", "753",
  "063", "163", "263", "363", "463", "563", "663", "763",
  "073", "173", "273", "373", "473", "573", "673", "773",
  "004", "104", "204", "304", "404", "504", "604", "704",
  "014", "114", "214", "314", "414", "514", "614", "714",
  "024", "124", "224", "324", "424", "524", "624", "724",
  "034", "134", "234", "334", "434", "534", "634", "734",
  "044", "144", "244", "344", "444", "544", "644", "744",
  "054", "154", "254", "354", "454", "554", "654", "754",
  "064", "164", "264", "364", "464", "564", "664", "764",
  "074", "174", "274", "374", "474", "574", "674", "774",
  "005", "105", "205", "305", "405", "505", "605", "705",
  "015", "115", "215", "315", "415", "515", "615", "715",
  "025", "125", "225", "325", "425", "525", "625", "725",
  "035", "135", "235", "335", "435", "535", "635", "735",
  "045", "145", "245", "345", "445", "545", "645", "745",
  "055", "155", "255", "355", "455", "555", "655", "755",
  "065", "165", "265", "365", "465", "565", "665", "765",
  "075", "175", "275", "375", "475", "575", "675", "775",
  "006", "106", "206", "306", "406", "506", "606", "706",
  "016", "116", "216", "316", "416", "516", "616", "716",
  "026", "126", "226", "326", "426", "526", "626", "726",
  "036", "136", "236", "336", "436", "536", "636", "736",
  "046", "146", "246", "346", "446", "546", "646", "746",
  "056", "156", "256", "356", "456", "556", "656", "756",
  "066", "166", "266", "366", "466", "566", "666", "766",
  "076", "176", "276", "376", "476", "576", "676", "776",
  "007", "107", "207", "307", "407", "507", "607", "707",
  "017", "117", "217", "317", "417", "517", "617", "717",
  "027", "127", "227", "327", "427", "527", "627", "727",
  "037", "137", "237", "337", "437", "537", "637", "737",
  "047", "147", "247", "347", "447", "547", "647", "747",
  "057", "157", "257", "357", "457", "557", "657", "757",
  "067", "167", "267", "367", "467", "567", "667", "767",
  "077", "177", "277", "377", "477", "577", "677", "777"
};

/** string table for decimal values */
static char *decimal[] = {
     "",   "1",   "2",   "3",   "4",   "5",   "6",   "7",   "8",   "9",
   "01",  "11",  "21",  "31",  "41",  "51",  "61",  "71",  "81",  "91",
   "02",  "12",  "22",  "32",  "42",  "52",  "62",  "72",  "82",  "92",
   "03",  "13",  "23",  "33",  "43",  "53",  "63",  "73",  "83",  "93",
   "04",  "14",  "24",  "34",  "44",  "54",  "64",  "74",  "84",  "94",
   "05",  "15",  "25",  "35",  "45",  "55",  "65",  "75",  "85",  "95",
   "06",  "16",  "26",  "36",  "46",  "56",  "66",  "76",  "86",  "96",
   "07",  "17",  "27",  "37",  "47",  "57",  "67",  "77",  "87",  "97",
   "08",  "18",  "28",  "38",  "48",  "58",  "68",  "78",  "88",  "98",
   "09",  "19",  "29",  "39",  "49",  "59",  "69",  "79",  "89",  "99",
  "001", "101", "201", "301", "401", "501", "601", "701", "801", "901",
  "011", "111", "211", "311", "411", "511", "611", "711", "811", "911",
  "021", "121", "221", "321", "421", "521", "621", "721", "821", "921",
  "031", "131", "231", "331", "431", "531", "631", "731", "831", "931",
  "041", "141", "241", "341", "441", "541", "641", "741", "841", "941",
  "051", "151", "251", "351", "451", "551", "651", "751", "851", "951",
  "061", "161", "261", "361", "461", "561", "661", "761", "861", "961",
  "071", "171", "271", "371", "471", "571", "671", "771", "871", "971",
  "081", "181", "281", "381", "481", "581", "681", "781", "881", "981",
  "091", "191", "291", "391", "491", "591", "691", "791", "891", "991",
  "002", "102", "202", "302", "402", "502", "602", "702", "802", "902",
  "012", "112", "212", "312", "412", "512", "612", "712", "812", "912",
  "022", "122", "222", "322", "422", "522", "622", "722", "822", "922",
  "032", "132", "232", "332", "432", "532", "632", "732", "832", "932",
  "042", "142", "242", "342", "442", "542", "642", "742", "842", "942",
  "052", "152", "252", "352", "452", "552", "652", "752", "852", "952",
  "062", "162", "262", "362", "462", "562", "662", "762", "862", "962",
  "072", "172", "272", "372", "472", "572", "672", "772", "872", "972",
  "082", "182", "282", "382", "482", "582", "682", "782", "882", "982",
  "092", "192", "292", "392", "492", "592", "692", "792", "892", "992",
  "003", "103", "203", "303", "403", "503", "603", "703", "803", "903",
  "013", "113", "213", "313", "413", "513", "613", "713", "813", "913",
  "023", "123", "223", "323", "423", "523", "623", "723", "823", "923",
  "033", "133", "233", "333", "433", "533", "633", "733", "833", "933",
  "043", "143", "243", "343", "443", "543", "643", "743", "843", "943",
  "053", "153", "253", "353", "453", "553", "653", "753", "853", "953",
  "063", "163", "263", "363", "463", "563", "663", "763", "863", "963",
  "073", "173", "273", "373", "473", "573", "673", "773", "873", "973",
  "083", "183", "283", "383", "483", "583", "683", "783", "883", "983",
  "093", "193", "293", "393", "493", "593", "693", "793", "893", "993",
  "004", "104", "204", "304", "404", "504", "604", "704", "804", "904",
  "014", "114", "214", "314", "414", "514", "614", "714", "814", "914",
  "024", "124", "224", "324", "424", "524", "624", "724", "824", "924",
  "034", "134", "234", "334", "434", "534", "634", "734", "834", "934",
  "044", "144", "244", "344", "444", "544", "644", "744", "844", "944",
  "054", "154", "254", "354", "454", "554", "654", "754", "854", "954",
  "064", "164", "264", "364", "464", "564", "664", "764", "864", "964",
  "074", "174", "274", "374", "474", "574", "674", "774", "874", "974",
  "084", "184", "284", "384", "484", "584", "684", "784", "884", "984",
  "094", "194", "294", "394", "494", "594", "694", "794", "894", "994",
  "005", "105", "205", "305", "405", "505", "605", "705", "805", "905",
  "015", "115", "215", "315", "415", "515", "615", "715", "815", "915",
  "025", "125", "225", "325", "425", "525", "625", "725", "825", "925",
  "035", "135", "235", "335", "435", "535", "635", "735", "835", "935",
  "045", "145", "245", "345", "445", "545", "645", "745", "845", "945",
  "055", "155", "255", "355", "455", "555", "655", "755", "855", "955",
  "065", "165", "265", "365", "465", "565", "665", "765", "865", "965",
  "075", "175", "275", "375", "475", "575", "675", "775", "875", "975",
  "085", "185", "285", "385", "485", "585", "685", "785", "885", "985",
  "095", "195", "295", "395", "495", "595", "695", "795", "895", "995",
  "006", "106", "206", "306", "406", "506", "606", "706", "806", "906",
  "016", "116", "216", "316", "416", "516", "616", "716", "816", "916",
  "026", "126", "226", "326", "426", "526", "626", "726", "826", "926",
  "036", "136", "236", "336", "436", "536", "636", "736", "836", "936",
  "046", "146", "246", "346", "446", "546", "646", "746", "846", "946",
  "056", "156", "256", "356", "456", "556", "656", "756", "856", "956",
  "066", "166", "266", "366", "466", "566", "666", "766", "866", "966",
  "076", "176", "276", "376", "476", "576", "676", "776", "876", "976",
  "086", "186", "286", "386", "486", "586", "686", "786", "886", "986",
  "096", "196", "296", "396", "496", "596", "696", "796", "896", "996",
  "007", "107", "207", "307", "407", "507", "607", "707", "807", "907",
  "017", "117", "217", "317", "417", "517", "617", "717", "817", "917",
  "027", "127", "227", "327", "427", "527", "627", "727", "827", "927",
  "037", "137", "237", "337", "437", "537", "637", "737", "837", "937",
  "047", "147", "247", "347", "447", "547", "647", "747", "847", "947",
  "057", "157", "257", "357", "457", "557", "657", "757", "857", "957",
  "067", "167", "267", "367", "467", "567", "667", "767", "867", "967",
  "077", "177", "277", "377", "477", "577", "677", "777", "877", "977",
  "087", "187", "287", "387", "487", "587", "687", "787", "887", "987",
  "097", "197", "297", "397", "497", "597", "697", "797", "897", "997",
  "008", "108", "208", "308", "408", "508", "608", "708", "808", "908",
  "018", "118", "218", "318", "418", "518", "618", "718", "818", "918",
  "028", "128", "228", "328", "428", "528", "628", "728", "828", "928",
  "038", "138", "238", "338", "438", "538", "638", "738", "838", "938",
  "048", "148", "248", "348", "448", "548", "648", "748", "848", "948",
  "058", "158", "258", "358", "458", "558", "658", "758", "858", "958",
  "068", "168", "268", "368", "468", "568", "668", "768", "868", "968",
  "078", "178", "278", "378", "478", "578", "678", "778", "878", "978",
  "088", "188", "288", "388", "488", "588", "688", "788", "888", "988",
  "098", "198", "298", "398", "498", "598", "698", "798", "898", "998",
  "009", "109", "209", "309", "409", "509", "609", "709", "809", "909",
  "019", "119", "219", "319", "419", "519", "619", "719", "819", "919",
  "029", "129", "229", "329", "429", "529", "629", "729", "829", "929",
  "039", "139", "239", "339", "439", "539", "639", "739", "839", "939",
  "049", "149", "249", "349", "449", "549", "649", "749", "849", "949",
  "059", "159", "259", "359", "459", "559", "659", "759", "859", "959",
  "069", "169", "269", "369", "469", "569", "669", "769", "869", "969",
  "079", "179", "279", "379", "479", "579", "679", "779", "879", "979",
  "089", "189", "289", "389", "489", "589", "689", "789", "889", "989",
  "099", "199", "299", "399", "499", "599", "699", "799", "899", "999"
};

/** string table for lower-case hexadecimal values */
static char *hex[] = {
     "",   "1",   "2",   "3",   "4",   "5",   "6",   "7",
    "8",   "9",   "a",   "b",   "c",   "d",   "e",   "f",
   "01",  "11",  "21",  "31",  "41",  "51",  "61",  "71",
   "81",  "91",  "a1",  "b1",  "c1",  "d1",  "e1",  "f1",
   "02",  "12",  "22",  "32",  "42",  "52",  "62",  "72",
   "82",  "92",  "a2",  "b2",  "c2",  "d2",  "e2",  "f2",
   "03",  "13",  "23",  "33",  "43",  "53",  "63",  "73",
   "83",  "93",  "a3",  "b3",  "c3",  "d3",  "e3",  "f3",
   "04",  "14",  "24",  "34",  "44",  "54",  "64",  "74",
   "84",  "94",  "a4",  "b4",  "c4",  "d4",  "e4",  "f4",
   "05",  "15",  "25",  "35",  "45",  "55",  "65",  "75",
   "85",  "95",  "a5",  "b5",  "c5",  "d5",  "e5",  "f5",
   "06",  "16",  "26",  "36",  "46",  "56",  "66",  "76",
   "86",  "96",  "a6",  "b6",  "c6",  "d6",  "e6",  "f6",
   "07",  "17",  "27",  "37",  "47",  "57",  "67",  "77",
   "87",  "97",  "a7",  "b7",  "c7",  "d7",  "e7",  "f7",
   "08",  "18",  "28",  "38",  "48",  "58",  "68",  "78",
   "88",  "98",  "a8",  "b8",  "c8",  "d8",  "e8",  "f8",
   "09",  "19",  "29",  "39",  "49",  "59",  "69",  "79",
   "89",  "99",  "a9",  "b9",  "c9",  "d9",  "e9",  "f9",
   "0a",  "1a",  "2a",  "3a",  "4a",  "5a",  "6a",  "7a",
   "8a",  "9a",  "aa",  "ba",  "ca",  "da",  "ea",  "fa",
   "0b",  "1b",  "2b",  "3b",  "4b",  "5b",  "6b",  "7b",
   "8b",  "9b",  "ab",  "bb",  "cb",  "db",  "eb",  "fb",
   "0c",  "1c",  "2c",  "3c",  "4c",  "5c",  "6c",  "7c",
   "8c",  "9c",  "ac",  "bc",  "cc",  "dc",  "ec",  "fc",
   "0d",  "1d",  "2d",  "3d",  "4d",  "5d",  "6d",  "7d",
   "8d",  "9d",  "ad",  "bd",  "cd",  "dd",  "ed",  "fd",
   "0e",  "1e",  "2e",  "3e",  "4e",  "5e",  "6e",  "7e",
   "8e",  "9e",  "ae",  "be",  "ce",  "de",  "ee",  "fe",
   "0f",  "1f",  "2f",  "3f",  "4f",  "5f",  "6f",  "7f",
   "8f",  "9f",  "af",  "bf",  "cf",  "df",  "ef",  "ff",
  "001", "101", "201", "301", "401", "501", "601", "701",
  "801", "901", "a01", "b01", "c01", "d01", "e01", "f01",
  "011", "111", "211", "311", "411", "511", "611", "711",
  "811", "911", "a11", "b11", "c11", "d11", "e11", "f11",
  "021", "121", "221", "321", "421", "521", "621", "721",
  "821", "921", "a21", "b21", "c21", "d21", "e21", "f21",
  "031", "131", "231", "331", "431", "531", "631", "731",
  "831", "931", "a31", "b31", "c31", "d31", "e31", "f31",
  "041", "141", "241", "341", "441", "541", "641", "741",
  "841", "941", "a41", "b41", "c41", "d41", "e41", "f41",
  "051", "151", "251", "351", "451", "551", "651", "751",
  "851", "951", "a51", "b51", "c51", "d51", "e51", "f51",
  "061", "161", "261", "361", "461", "561", "661", "761",
  "861", "961", "a61", "b61", "c61", "d61", "e61", "f61",
  "071", "171", "271", "371", "471", "571", "671", "771",
  "871", "971", "a71", "b71", "c71", "d71", "e71", "f71",
  "081", "181", "281", "381", "481", "581", "681", "781",
  "881", "981", "a81", "b81", "c81", "d81", "e81", "f81",
  "091", "191", "291", "391", "491", "591", "691", "791",
  "891", "991", "a91", "b91", "c91", "d91", "e91", "f91",
  "0a1", "1a1", "2a1", "3a1", "4a1", "5a1", "6a1", "7a1",
  "8a1", "9a1", "aa1", "ba1", "ca1", "da1", "ea1", "fa1",
  "0b1", "1b1", "2b1", "3b1", "4b1", "5b1", "6b1", "7b1",
  "8b1", "9b1", "ab1", "bb1", "cb1", "db1", "eb1", "fb1",
  "0c1", "1c1", "2c1", "3c1", "4c1", "5c1", "6c1", "7c1",
  "8c1", "9c1", "ac1", "bc1", "cc1", "dc1", "ec1", "fc1",
  "0d1", "1d1", "2d1", "3d1", "4d1", "5d1", "6d1", "7d1",
  "8d1", "9d1", "ad1", "bd1", "cd1", "dd1", "ed1", "fd1",
  "0e1", "1e1", "2e1", "3e1", "4e1", "5e1", "6e1", "7e1",
  "8e1", "9e1", "ae1", "be1", "ce1", "de1", "ee1", "fe1",
  "0f1", "1f1", "2f1", "3f1", "4f1", "5f1", "6f1", "7f1",
  "8f1", "9f1", "af1", "bf1", "cf1", "df1", "ef1", "ff1",
  "002", "102", "202", "302", "402", "502", "602", "702",
  "802", "902", "a02", "b02", "c02", "d02", "e02", "f02",
  "012", "112", "212", "312", "412", "512", "612", "712",
  "812", "912", "a12", "b12", "c12", "d12", "e12", "f12",
  "022", "122", "222", "322", "422", "522", "622", "722",
  "822", "922", "a22", "b22", "c22", "d22", "e22", "f22",
  "032", "132", "232", "332", "432", "532", "632", "732",
  "832", "932", "a32", "b32", "c32", "d32", "e32", "f32",
  "042", "142", "242", "342", "442", "542", "642", "742",
  "842", "942", "a42", "b42", "c42", "d42", "e42", "f42",
  "052", "152", "252", "352", "452", "552", "652", "752",
  "852", "952", "a52", "b52", "c52", "d52", "e52", "f52",
  "062", "162", "262", "362", "462", "562", "662", "762",
  "862", "962", "a62", "b62", "c62", "d62", "e62", "f62",
  "072", "172", "272", "372", "472", "572", "672", "772",
  "872", "972", "a72", "b72", "c72", "d72", "e72", "f72",
  "082", "182", "282", "382", "482", "582", "682", "782",
  "882", "982", "a82", "b82", "c82", "d82", "e82", "f82",
  "092", "192", "292", "392", "492", "592", "692", "792",
  "892", "992", "a92", "b92", "c92", "d92", "e92", "f92",
  "0a2", "1a2", "2a2", "3a2", "4a2", "5a2", "6a2", "7a2",
  "8a2", "9a2", "aa2", "ba2", "ca2", "da2", "ea2", "fa2",
  "0b2", "1b2", "2b2", "3b2", "4b2", "5b2", "6b2", "7b2",
  "8b2", "9b2", "ab2", "bb2", "cb2", "db2", "eb2", "fb2",
  "0c2", "1c2", "2c2", "3c2", "4c2", "5c2", "6c2", "7c2",
  "8c2", "9c2", "ac2", "bc2", "cc2", "dc2", "ec2", "fc2",
  "0d2", "1d2", "2d2", "3d2", "4d2", "5d2", "6d2", "7d2",
  "8d2", "9d2", "ad2", "bd2", "cd2", "dd2", "ed2", "fd2",
  "0e2", "1e2", "2e2", "3e2", "4e2", "5e2", "6e2", "7e2",
  "8e2", "9e2", "ae2", "be2", "ce2", "de2", "ee2", "fe2",
  "0f2", "1f2", "2f2", "3f2", "4f2", "5f2", "6f2", "7f2",
  "8f2", "9f2", "af2", "bf2", "cf2", "df2", "ef2", "ff2",
  "003", "103", "203", "303", "403", "503", "603", "703",
  "803", "903", "a03", "b03", "c03", "d03", "e03", "f03",
  "013", "113", "213", "313", "413", "513", "613", "713",
  "813", "913", "a13", "b13", "c13", "d13", "e13", "f13",
  "023", "123", "223", "323", "423", "523", "623", "723",
  "823", "923", "a23", "b23", "c23", "d23", "e23", "f23",
  "033", "133", "233", "333", "433", "533", "633", "733",
  "833", "933", "a33", "b33", "c33", "d33", "e33", "f33",
  "043", "143", "243", "343", "443", "543", "643", "743",
  "843", "943", "a43", "b43", "c43", "d43", "e43", "f43",
  "053", "153", "253", "353", "453", "553", "653", "753",
  "853", "953", "a53", "b53", "c53", "d53", "e53", "f53",
  "063", "163", "263", "363", "463", "563", "663", "763",
  "863", "963", "a63", "b63", "c63", "d63", "e63", "f63",
  "073", "173", "273", "373", "473", "573", "673", "773",
  "873", "973", "a73", "b73", "c73", "d73", "e73", "f73",
  "083", "183", "283", "383", "483", "583", "683", "783",
  "883", "983", "a83", "b83", "c83", "d83", "e83", "f83",
  "093", "193", "293", "393", "493", "593", "693", "793",
  "893", "993", "a93", "b93", "c93", "d93", "e93", "f93",
  "0a3", "1a3", "2a3", "3a3", "4a3", "5a3", "6a3", "7a3",
  "8a3", "9a3", "aa3", "ba3", "ca3", "da3", "ea3", "fa3",
  "0b3", "1b3", "2b3", "3b3", "4b3", "5b3", "6b3", "7b3",
  "8b3", "9b3", "ab3", "bb3", "cb3", "db3", "eb3", "fb3",
  "0c3", "1c3", "2c3", "3c3", "4c3", "5c3", "6c3", "7c3",
  "8c3", "9c3", "ac3", "bc3", "cc3", "dc3", "ec3", "fc3",
  "0d3", "1d3", "2d3", "3d3", "4d3", "5d3", "6d3", "7d3",
  "8d3", "9d3", "ad3", "bd3", "cd3", "dd3", "ed3", "fd3",
  "0e3", "1e3", "2e3", "3e3", "4e3", "5e3", "6e3", "7e3",
  "8e3", "9e3", "ae3", "be3", "ce3", "de3", "ee3", "fe3",
  "0f3", "1f3", "2f3", "3f3", "4f3", "5f3", "6f3", "7f3",
  "8f3", "9f3", "af3", "bf3", "cf3", "df3", "ef3", "ff3",
  "004", "104", "204", "304", "404", "504", "604", "704",
  "804", "904", "a04", "b04", "c04", "d04", "e04", "f04",
  "014", "114", "214", "314", "414", "514", "614", "714",
  "814", "914", "a14", "b14", "c14", "d14", "e14", "f14",
  "024", "124", "224", "324", "424", "524", "624", "724",
  "824", "924", "a24", "b24", "c24", "d24", "e24", "f24",
  "034", "134", "234", "334", "434", "534", "634", "734",
  "834", "934", "a34", "b34", "c34", "d34", "e34", "f34",
  "044", "144", "244", "344", "444", "544", "644", "744",
  "844", "944", "a44", "b44", "c44", "d44", "e44", "f44",
  "054", "154", "254", "354", "454", "554", "654", "754",
  "854", "954", "a54", "b54", "c54", "d54", "e54", "f54",
  "064", "164", "264", "364", "464", "564", "664", "764",
  "864", "964", "a64", "b64", "c64", "d64", "e64", "f64",
  "074", "174", "274", "374", "474", "574", "674", "774",
  "874", "974", "a74", "b74", "c74", "d74", "e74", "f74",
  "084", "184", "284", "384", "484", "584", "684", "784",
  "884", "984", "a84", "b84", "c84", "d84", "e84", "f84",
  "094", "194", "294", "394", "494", "594", "694", "794",
  "894", "994", "a94", "b94", "c94", "d94", "e94", "f94",
  "0a4", "1a4", "2a4", "3a4", "4a4", "5a4", "6a4", "7a4",
  "8a4", "9a4", "aa4", "ba4", "ca4", "da4", "ea4", "fa4",
  "0b4", "1b4", "2b4", "3b4", "4b4", "5b4", "6b4", "7b4",
  "8b4", "9b4", "ab4", "bb4", "cb4", "db4", "eb4", "fb4",
  "0c4", "1c4", "2c4", "3c4", "4c4", "5c4", "6c4", "7c4",
  "8c4", "9c4", "ac4", "bc4", "cc4", "dc4", "ec4", "fc4",
  "0d4", "1d4", "2d4", "3d4", "4d4", "5d4", "6d4", "7d4",
  "8d4", "9d4", "ad4", "bd4", "cd4", "dd4", "ed4", "fd4",
  "0e4", "1e4", "2e4", "3e4", "4e4", "5e4", "6e4", "7e4",
  "8e4", "9e4", "ae4", "be4", "ce4", "de4", "ee4", "fe4",
  "0f4", "1f4", "2f4", "3f4", "4f4", "5f4", "6f4", "7f4",
  "8f4", "9f4", "af4", "bf4", "cf4", "df4", "ef4", "ff4",
  "005", "105", "205", "305", "405", "505", "605", "705",
  "805", "905", "a05", "b05", "c05", "d05", "e05", "f05",
  "015", "115", "215", "315", "415", "515", "615", "715",
  "815", "915", "a15", "b15", "c15", "d15", "e15", "f15",
  "025", "125", "225", "325", "425", "525", "625", "725",
  "825", "925", "a25", "b25", "c25", "d25", "e25", "f25",
  "035", "135", "235", "335", "435", "535", "635", "735",
  "835", "935", "a35", "b35", "c35", "d35", "e35", "f35",
  "045", "145", "245", "345", "445", "545", "645", "745",
  "845", "945", "a45", "b45", "c45", "d45", "e45", "f45",
  "055", "155", "255", "355", "455", "555", "655", "755",
  "855", "955", "a55", "b55", "c55", "d55", "e55", "f55",
  "065", "165", "265", "365", "465", "565", "665", "765",
  "865", "965", "a65", "b65", "c65", "d65", "e65", "f65",
  "075", "175", "275", "375", "475", "575", "675", "775",
  "875", "975", "a75", "b75", "c75", "d75", "e75", "f75",
  "085", "185", "285", "385", "485", "585", "685", "785",
  "885", "985", "a85", "b85", "c85", "d85", "e85", "f85",
  "095", "195", "295", "395", "495", "595", "695", "795",
  "895", "995", "a95", "b95", "c95", "d95", "e95", "f95",
  "0a5", "1a5", "2a5", "3a5", "4a5", "5a5", "6a5", "7a5",
  "8a5", "9a5", "aa5", "ba5", "ca5", "da5", "ea5", "fa5",
  "0b5", "1b5", "2b5", "3b5", "4b5", "5b5", "6b5", "7b5",
  "8b5", "9b5", "ab5", "bb5", "cb5", "db5", "eb5", "fb5",
  "0c5", "1c5", "2c5", "3c5", "4c5", "5c5", "6c5", "7c5",
  "8c5", "9c5", "ac5", "bc5", "cc5", "dc5", "ec5", "fc5",
  "0d5", "1d5", "2d5", "3d5", "4d5", "5d5", "6d5", "7d5",
  "8d5", "9d5", "ad5", "bd5", "cd5", "dd5", "ed5", "fd5",
  "0e5", "1e5", "2e5", "3e5", "4e5", "5e5", "6e5", "7e5",
  "8e5", "9e5", "ae5", "be5", "ce5", "de5", "ee5", "fe5",
  "0f5", "1f5", "2f5", "3f5", "4f5", "5f5", "6f5", "7f5",
  "8f5", "9f5", "af5", "bf5", "cf5", "df5", "ef5", "ff5",
  "006", "106", "206", "306", "406", "506", "606", "706",
  "806", "906", "a06", "b06", "c06", "d06", "e06", "f06",
  "016", "116", "216", "316", "416", "516", "616", "716",
  "816", "916", "a16", "b16", "c16", "d16", "e16", "f16",
  "026", "126", "226", "326", "426", "526", "626", "726",
  "826", "926", "a26", "b26", "c26", "d26", "e26", "f26",
  "036", "136", "236", "336", "436", "536", "636", "736",
  "836", "936", "a36", "b36", "c36", "d36", "e36", "f36",
  "046", "146", "246", "346", "446", "546", "646", "746",
  "846", "946", "a46", "b46", "c46", "d46", "e46", "f46",
  "056", "156", "256", "356", "456", "556", "656", "756",
  "856", "956", "a56", "b56", "c56", "d56", "e56", "f56",
  "066", "166", "266", "366", "466", "566", "666", "766",
  "866", "966", "a66", "b66", "c66", "d66", "e66", "f66",
  "076", "176", "276", "376", "476", "576", "676", "776",
  "876", "976", "a76", "b76", "c76", "d76", "e76", "f76",
  "086", "186", "286", "386", "486", "586", "686", "786",
  "886", "986", "a86", "b86", "c86", "d86", "e86", "f86",
  "096", "196", "296", "396", "496", "596", "696", "796",
  "896", "996", "a96", "b96", "c96", "d96", "e96", "f96",
  "0a6", "1a6", "2a6", "3a6", "4a6", "5a6", "6a6", "7a6",
  "8a6", "9a6", "aa6", "ba6", "ca6", "da6", "ea6", "fa6",
  "0b6", "1b6", "2b6", "3b6", "4b6", "5b6", "6b6", "7b6",
  "8b6", "9b6", "ab6", "bb6", "cb6", "db6", "eb6", "fb6",
  "0c6", "1c6", "2c6", "3c6", "4c6", "5c6", "6c6", "7c6",
  "8c6", "9c6", "ac6", "bc6", "cc6", "dc6", "ec6", "fc6",
  "0d6", "1d6", "2d6", "3d6", "4d6", "5d6", "6d6", "7d6",
  "8d6", "9d6", "ad6", "bd6", "cd6", "dd6", "ed6", "fd6",
  "0e6", "1e6", "2e6", "3e6", "4e6", "5e6", "6e6", "7e6",
  "8e6", "9e6", "ae6", "be6", "ce6", "de6", "ee6", "fe6",
  "0f6", "1f6", "2f6", "3f6", "4f6", "5f6", "6f6", "7f6",
  "8f6", "9f6", "af6", "bf6", "cf6", "df6", "ef6", "ff6",
  "007", "107", "207", "307", "407", "507", "607", "707",
  "807", "907", "a07", "b07", "c07", "d07", "e07", "f07",
  "017", "117", "217", "317", "417", "517", "617", "717",
  "817", "917", "a17", "b17", "c17", "d17", "e17", "f17",
  "027", "127", "227", "327", "427", "527", "627", "727",
  "827", "927", "a27", "b27", "c27", "d27", "e27", "f27",
  "037", "137", "237", "337", "437", "537", "637", "737",
  "837", "937", "a37", "b37", "c37", "d37", "e37", "f37",
  "047", "147", "247", "347", "447", "547", "647", "747",
  "847", "947", "a47", "b47", "c47", "d47", "e47", "f47",
  "057", "157", "257", "357", "457", "557", "657", "757",
  "857", "957", "a57", "b57", "c57", "d57", "e57", "f57",
  "067", "167", "267", "367", "467", "567", "667", "767",
  "867", "967", "a67", "b67", "c67", "d67", "e67", "f67",
  "077", "177", "277", "377", "477", "577", "677", "777",
  "877", "977", "a77", "b77", "c77", "d77", "e77", "f77",
  "087", "187", "287", "387", "487", "587", "687", "787",
  "887", "987", "a87", "b87", "c87", "d87", "e87", "f87",
  "097", "197", "297", "397", "497", "597", "697", "797",
  "897", "997", "a97", "b97", "c97", "d97", "e97", "f97",
  "0a7", "1a7", "2a7", "3a7", "4a7", "5a7", "6a7", "7a7",
  "8a7", "9a7", "aa7", "ba7", "ca7", "da7", "ea7", "fa7",
  "0b7", "1b7", "2b7", "3b7", "4b7", "5b7", "6b7", "7b7",
  "8b7", "9b7", "ab7", "bb7", "cb7", "db7", "eb7", "fb7",
  "0c7", "1c7", "2c7", "3c7", "4c7", "5c7", "6c7", "7c7",
  "8c7", "9c7", "ac7", "bc7", "cc7", "dc7", "ec7", "fc7",
  "0d7", "1d7", "2d7", "3d7", "4d7", "5d7", "6d7", "7d7",
  "8d7", "9d7", "ad7", "bd7", "cd7", "dd7", "ed7", "fd7",
  "0e7", "1e7", "2e7", "3e7", "4e7", "5e7", "6e7", "7e7",
  "8e7", "9e7", "ae7", "be7", "ce7", "de7", "ee7", "fe7",
  "0f7", "1f7", "2f7", "3f7", "4f7", "5f7", "6f7", "7f7",
  "8f7", "9f7", "af7", "bf7", "cf7", "df7", "ef7", "ff7",
  "008", "108", "208", "308", "408", "508", "608", "708",
  "808", "908", "a08", "b08", "c08", "d08", "e08", "f08",
  "018", "118", "218", "318", "418", "518", "618", "718",
  "818", "918", "a18", "b18", "c18", "d18", "e18", "f18",
  "028", "128", "228", "328", "428", "528", "628", "728",
  "828", "928", "a28", "b28", "c28", "d28", "e28", "f28",
  "038", "138", "238", "338", "438", "538", "638", "738",
  "838", "938", "a38", "b38", "c38", "d38", "e38", "f38",
  "048", "148", "248", "348", "448", "548", "648", "748",
  "848", "948", "a48", "b48", "c48", "d48", "e48", "f48",
  "058", "158", "258", "358", "458", "558", "658", "758",
  "858", "958", "a58", "b58", "c58", "d58", "e58", "f58",
  "068", "168", "268", "368", "468", "568", "668", "768",
  "868", "968", "a68", "b68", "c68", "d68", "e68", "f68",
  "078", "178", "278", "378", "478", "578", "678", "778",
  "878", "978", "a78", "b78", "c78", "d78", "e78", "f78",
  "088", "188", "288", "388", "488", "588", "688", "788",
  "888", "988", "a88", "b88", "c88", "d88", "e88", "f88",
  "098", "198", "298", "398", "498", "598", "698", "798",
  "898", "998", "a98", "b98", "c98", "d98", "e98", "f98",
  "0a8", "1a8", "2a8", "3a8", "4a8", "5a8", "6a8", "7a8",
  "8a8", "9a8", "aa8", "ba8", "ca8", "da8", "ea8", "fa8",
  "0b8", "1b8", "2b8", "3b8", "4b8", "5b8", "6b8", "7b8",
  "8b8", "9b8", "ab8", "bb8", "cb8", "db8", "eb8", "fb8",
  "0c8", "1c8", "2c8", "3c8", "4c8", "5c8", "6c8", "7c8",
  "8c8", "9c8", "ac8", "bc8", "cc8", "dc8", "ec8", "fc8",
  "0d8", "1d8", "2d8", "3d8", "4d8", "5d8", "6d8", "7d8",
  "8d8", "9d8", "ad8", "bd8", "cd8", "dd8", "ed8", "fd8",
  "0e8", "1e8", "2e8", "3e8", "4e8", "5e8", "6e8", "7e8",
  "8e8", "9e8", "ae8", "be8", "ce8", "de8", "ee8", "fe8",
  "0f8", "1f8", "2f8", "3f8", "4f8", "5f8", "6f8", "7f8",
  "8f8", "9f8", "af8", "bf8", "cf8", "df8", "ef8", "ff8",
  "009", "109", "209", "309", "409", "509", "609", "709",
  "809", "909", "a09", "b09", "c09", "d09", "e09", "f09",
  "019", "119", "219", "319", "419", "519", "619", "719",
  "819", "919", "a19", "b19", "c19", "d19", "e19", "f19",
  "029", "129", "229", "329", "429", "529", "629", "729",
  "829", "929", "a29", "b29", "c29", "d29", "e29", "f29",
  "039", "139", "239", "339", "439", "539", "639", "739",
  "839", "939", "a39", "b39", "c39", "d39", "e39", "f39",
  "049", "149", "249", "349", "449", "549", "649", "749",
  "849", "949", "a49", "b49", "c49", "d49", "e49", "f49",
  "059", "159", "259", "359", "459", "559", "659", "759",
  "859", "959", "a59", "b59", "c59", "d59", "e59", "f59",
  "069", "169", "269", "369", "469", "569", "669", "769",
  "869", "969", "a69", "b69", "c69", "d69", "e69", "f69",
  "079", "179", "279", "379", "479", "579", "679", "779",
  "879", "979", "a79", "b79", "c79", "d79", "e79", "f79",
  "089", "189", "289", "389", "489", "589", "689", "789",
  "889", "989", "a89", "b89", "c89", "d89", "e89", "f89",
  "099", "199", "299", "399", "499", "599", "699", "799",
  "899", "999", "a99", "b99", "c99", "d99", "e99", "f99",
  "0a9", "1a9", "2a9", "3a9", "4a9", "5a9", "6a9", "7a9",
  "8a9", "9a9", "aa9", "ba9", "ca9", "da9", "ea9", "fa9",
  "0b9", "1b9", "2b9", "3b9", "4b9", "5b9", "6b9", "7b9",
  "8b9", "9b9", "ab9", "bb9", "cb9", "db9", "eb9", "fb9",
  "0c9", "1c9", "2c9", "3c9", "4c9", "5c9", "6c9", "7c9",
  "8c9", "9c9", "ac9", "bc9", "cc9", "dc9", "ec9", "fc9",
  "0d9", "1d9", "2d9", "3d9", "4d9", "5d9", "6d9", "7d9",
  "8d9", "9d9", "ad9", "bd9", "cd9", "dd9", "ed9", "fd9",
  "0e9", "1e9", "2e9", "3e9", "4e9", "5e9", "6e9", "7e9",
  "8e9", "9e9", "ae9", "be9", "ce9", "de9", "ee9", "fe9",
  "0f9", "1f9", "2f9", "3f9", "4f9", "5f9", "6f9", "7f9",
  "8f9", "9f9", "af9", "bf9", "cf9", "df9", "ef9", "ff9",
  "00a", "10a", "20a", "30a", "40a", "50a", "60a", "70a",
  "80a", "90a", "a0a", "b0a", "c0a", "d0a", "e0a", "f0a",
  "01a", "11a", "21a", "31a", "41a", "51a", "61a", "71a",
  "81a", "91a", "a1a", "b1a", "c1a", "d1a", "e1a", "f1a",
  "02a", "12a", "22a", "32a", "42a", "52a", "62a", "72a",
  "82a", "92a", "a2a", "b2a", "c2a", "d2a", "e2a", "f2a",
  "03a", "13a", "23a", "33a", "43a", "53a", "63a", "73a",
  "83a", "93a", "a3a", "b3a", "c3a", "d3a", "e3a", "f3a",
  "04a", "14a", "24a", "34a", "44a", "54a", "64a", "74a",
  "84a", "94a", "a4a", "b4a", "c4a", "d4a", "e4a", "f4a",
  "05a", "15a", "25a", "35a", "45a", "55a", "65a", "75a",
  "85a", "95a", "a5a", "b5a", "c5a", "d5a", "e5a", "f5a",
  "06a", "16a", "26a", "36a", "46a", "56a", "66a", "76a",
  "86a", "96a", "a6a", "b6a", "c6a", "d6a", "e6a", "f6a",
  "07a", "17a", "27a", "37a", "47a", "57a", "67a", "77a",
  "87a", "97a", "a7a", "b7a", "c7a", "d7a", "e7a", "f7a",
  "08a", "18a", "28a", "38a", "48a", "58a", "68a", "78a",
  "88a", "98a", "a8a", "b8a", "c8a", "d8a", "e8a", "f8a",
  "09a", "19a", "29a", "39a", "49a", "59a", "69a", "79a",
  "89a", "99a", "a9a", "b9a", "c9a", "d9a", "e9a", "f9a",
  "0aa", "1aa", "2aa", "3aa", "4aa", "5aa", "6aa", "7aa",
  "8aa", "9aa", "aaa", "baa", "caa", "daa", "eaa", "faa",
  "0ba", "1ba", "2ba", "3ba", "4ba", "5ba", "6ba", "7ba",
  "8ba", "9ba", "aba", "bba", "cba", "dba", "eba", "fba",
  "0ca", "1ca", "2ca", "3ca", "4ca", "5ca", "6ca", "7ca",
  "8ca", "9ca", "aca", "bca", "cca", "dca", "eca", "fca",
  "0da", "1da", "2da", "3da", "4da", "5da", "6da", "7da",
  "8da", "9da", "ada", "bda", "cda", "dda", "eda", "fda",
  "0ea", "1ea", "2ea", "3ea", "4ea", "5ea", "6ea", "7ea",
  "8ea", "9ea", "aea", "bea", "cea", "dea", "eea", "fea",
  "0fa", "1fa", "2fa", "3fa", "4fa", "5fa", "6fa", "7fa",
  "8fa", "9fa", "afa", "bfa", "cfa", "dfa", "efa", "ffa",
  "00b", "10b", "20b", "30b", "40b", "50b", "60b", "70b",
  "80b", "90b", "a0b", "b0b", "c0b", "d0b", "e0b", "f0b",
  "01b", "11b", "21b", "31b", "41b", "51b", "61b", "71b",
  "81b", "91b", "a1b", "b1b", "c1b", "d1b", "e1b", "f1b",
  "02b", "12b", "22b", "32b", "42b", "52b", "62b", "72b",
  "82b", "92b", "a2b", "b2b", "c2b", "d2b", "e2b", "f2b",
  "03b", "13b", "23b", "33b", "43b", "53b", "63b", "73b",
  "83b", "93b", "a3b", "b3b", "c3b", "d3b", "e3b", "f3b",
  "04b", "14b", "24b", "34b", "44b", "54b", "64b", "74b",
  "84b", "94b", "a4b", "b4b", "c4b", "d4b", "e4b", "f4b",
  "05b", "15b", "25b", "35b", "45b", "55b", "65b", "75b",
  "85b", "95b", "a5b", "b5b", "c5b", "d5b", "e5b", "f5b",
  "06b", "16b", "26b", "36b", "46b", "56b", "66b", "76b",
  "86b", "96b", "a6b", "b6b", "c6b", "d6b", "e6b", "f6b",
  "07b", "17b", "27b", "37b", "47b", "57b", "67b", "77b",
  "87b", "97b", "a7b", "b7b", "c7b", "d7b", "e7b", "f7b",
  "08b", "18b", "28b", "38b", "48b", "58b", "68b", "78b",
  "88b", "98b", "a8b", "b8b", "c8b", "d8b", "e8b", "f8b",
  "09b", "19b", "29b", "39b", "49b", "59b", "69b", "79b",
  "89b", "99b", "a9b", "b9b", "c9b", "d9b", "e9b", "f9b",
  "0ab", "1ab", "2ab", "3ab", "4ab", "5ab", "6ab", "7ab",
  "8ab", "9ab", "aab", "bab", "cab", "dab", "eab", "fab",
  "0bb", "1bb", "2bb", "3bb", "4bb", "5bb", "6bb", "7bb",
  "8bb", "9bb", "abb", "bbb", "cbb", "dbb", "ebb", "fbb",
  "0cb", "1cb", "2cb", "3cb", "4cb", "5cb", "6cb", "7cb",
  "8cb", "9cb", "acb", "bcb", "ccb", "dcb", "ecb", "fcb",
  "0db", "1db", "2db", "3db", "4db", "5db", "6db", "7db",
  "8db", "9db", "adb", "bdb", "cdb", "ddb", "edb", "fdb",
  "0eb", "1eb", "2eb", "3eb", "4eb", "5eb", "6eb", "7eb",
  "8eb", "9eb", "aeb", "beb", "ceb", "deb", "eeb", "feb",
  "0fb", "1fb", "2fb", "3fb", "4fb", "5fb", "6fb", "7fb",
  "8fb", "9fb", "afb", "bfb", "cfb", "dfb", "efb", "ffb",
  "00c", "10c", "20c", "30c", "40c", "50c", "60c", "70c",
  "80c", "90c", "a0c", "b0c", "c0c", "d0c", "e0c", "f0c",
  "01c", "11c", "21c", "31c", "41c", "51c", "61c", "71c",
  "81c", "91c", "a1c", "b1c", "c1c", "d1c", "e1c", "f1c",
  "02c", "12c", "22c", "32c", "42c", "52c", "62c", "72c",
  "82c", "92c", "a2c", "b2c", "c2c", "d2c", "e2c", "f2c",
  "03c", "13c", "23c", "33c", "43c", "53c", "63c", "73c",
  "83c", "93c", "a3c", "b3c", "c3c", "d3c", "e3c", "f3c",
  "04c", "14c", "24c", "34c", "44c", "54c", "64c", "74c",
  "84c", "94c", "a4c", "b4c", "c4c", "d4c", "e4c", "f4c",
  "05c", "15c", "25c", "35c", "45c", "55c", "65c", "75c",
  "85c", "95c", "a5c", "b5c", "c5c", "d5c", "e5c", "f5c",
  "06c", "16c", "26c", "36c", "46c", "56c", "66c", "76c",
  "86c", "96c", "a6c", "b6c", "c6c", "d6c", "e6c", "f6c",
  "07c", "17c", "27c", "37c", "47c", "57c", "67c", "77c",
  "87c", "97c", "a7c", "b7c", "c7c", "d7c", "e7c", "f7c",
  "08c", "18c", "28c", "38c", "48c", "58c", "68c", "78c",
  "88c", "98c", "a8c", "b8c", "c8c", "d8c", "e8c", "f8c",
  "09c", "19c", "29c", "39c", "49c", "59c", "69c", "79c",
  "89c", "99c", "a9c", "b9c", "c9c", "d9c", "e9c", "f9c",
  "0ac", "1ac", "2ac", "3ac", "4ac", "5ac", "6ac", "7ac",
  "8ac", "9ac", "aac", "bac", "cac", "dac", "eac", "fac",
  "0bc", "1bc", "2bc", "3bc", "4bc", "5bc", "6bc", "7bc",
  "8bc", "9bc", "abc", "bbc", "cbc", "dbc", "ebc", "fbc",
  "0cc", "1cc", "2cc", "3cc", "4cc", "5cc", "6cc", "7cc",
  "8cc", "9cc", "acc", "bcc", "ccc", "dcc", "ecc", "fcc",
  "0dc", "1dc", "2dc", "3dc", "4dc", "5dc", "6dc", "7dc",
  "8dc", "9dc", "adc", "bdc", "cdc", "ddc", "edc", "fdc",
  "0ec", "1ec", "2ec", "3ec", "4ec", "5ec", "6ec", "7ec",
  "8ec", "9ec", "aec", "bec", "cec", "dec", "eec", "fec",
  "0fc", "1fc", "2fc", "3fc", "4fc", "5fc", "6fc", "7fc",
  "8fc", "9fc", "afc", "bfc", "cfc", "dfc", "efc", "ffc",
  "00d", "10d", "20d", "30d", "40d", "50d", "60d", "70d",
  "80d", "90d", "a0d", "b0d", "c0d", "d0d", "e0d", "f0d",
  "01d", "11d", "21d", "31d", "41d", "51d", "61d", "71d",
  "81d", "91d", "a1d", "b1d", "c1d", "d1d", "e1d", "f1d",
  "02d", "12d", "22d", "32d", "42d", "52d", "62d", "72d",
  "82d", "92d", "a2d", "b2d", "c2d", "d2d", "e2d", "f2d",
  "03d", "13d", "23d", "33d", "43d", "53d", "63d", "73d",
  "83d", "93d", "a3d", "b3d", "c3d", "d3d", "e3d", "f3d",
  "04d", "14d", "24d", "34d", "44d", "54d", "64d", "74d",
  "84d", "94d", "a4d", "b4d", "c4d", "d4d", "e4d", "f4d",
  "05d", "15d", "25d", "35d", "45d", "55d", "65d", "75d",
  "85d", "95d", "a5d", "b5d", "c5d", "d5d", "e5d", "f5d",
  "06d", "16d", "26d", "36d", "46d", "56d", "66d", "76d",
  "86d", "96d", "a6d", "b6d", "c6d", "d6d", "e6d", "f6d",
  "07d", "17d", "27d", "37d", "47d", "57d", "67d", "77d",
  "87d", "97d", "a7d", "b7d", "c7d", "d7d", "e7d", "f7d",
  "08d", "18d", "28d", "38d", "48d", "58d", "68d", "78d",
  "88d", "98d", "a8d", "b8d", "c8d", "d8d", "e8d", "f8d",
  "09d", "19d", "29d", "39d", "49d", "59d", "69d", "79d",
  "89d", "99d", "a9d", "b9d", "c9d", "d9d", "e9d", "f9d",
  "0ad", "1ad", "2ad", "3ad", "4ad", "5ad", "6ad", "7ad",
  "8ad", "9ad", "aad", "bad", "cad", "dad", "ead", "fad",
  "0bd", "1bd", "2bd", "3bd", "4bd", "5bd", "6bd", "7bd",
  "8bd", "9bd", "abd", "bbd", "cbd", "dbd", "ebd", "fbd",
  "0cd", "1cd", "2cd", "3cd", "4cd", "5cd", "6cd", "7cd",
  "8cd", "9cd", "acd", "bcd", "ccd", "dcd", "ecd", "fcd",
  "0dd", "1dd", "2dd", "3dd", "4dd", "5dd", "6dd", "7dd",
  "8dd", "9dd", "add", "bdd", "cdd", "ddd", "edd", "fdd",
  "0ed", "1ed", "2ed", "3ed", "4ed", "5ed", "6ed", "7ed",
  "8ed", "9ed", "aed", "bed", "ced", "ded", "eed", "fed",
  "0fd", "1fd", "2fd", "3fd", "4fd", "5fd", "6fd", "7fd",
  "8fd", "9fd", "afd", "bfd", "cfd", "dfd", "efd", "ffd",
  "00e", "10e", "20e", "30e", "40e", "50e", "60e", "70e",
  "80e", "90e", "a0e", "b0e", "c0e", "d0e", "e0e", "f0e",
  "01e", "11e", "21e", "31e", "41e", "51e", "61e", "71e",
  "81e", "91e", "a1e", "b1e", "c1e", "d1e", "e1e", "f1e",
  "02e", "12e", "22e", "32e", "42e", "52e", "62e", "72e",
  "82e", "92e", "a2e", "b2e", "c2e", "d2e", "e2e", "f2e",
  "03e", "13e", "23e", "33e", "43e", "53e", "63e", "73e",
  "83e", "93e", "a3e", "b3e", "c3e", "d3e", "e3e", "f3e",
  "04e", "14e", "24e", "34e", "44e", "54e", "64e", "74e",
  "84e", "94e", "a4e", "b4e", "c4e", "d4e", "e4e", "f4e",
  "05e", "15e", "25e", "35e", "45e", "55e", "65e", "75e",
  "85e", "95e", "a5e", "b5e", "c5e", "d5e", "e5e", "f5e",
  "06e", "16e", "26e", "36e", "46e", "56e", "66e", "76e",
  "86e", "96e", "a6e", "b6e", "c6e", "d6e", "e6e", "f6e",
  "07e", "17e", "27e", "37e", "47e", "57e", "67e", "77e",
  "87e", "97e", "a7e", "b7e", "c7e", "d7e", "e7e", "f7e",
  "08e", "18e", "28e", "38e", "48e", "58e", "68e", "78e",
  "88e", "98e", "a8e", "b8e", "c8e", "d8e", "e8e", "f8e",
  "09e", "19e", "29e", "39e", "49e", "59e", "69e", "79e",
  "89e", "99e", "a9e", "b9e", "c9e", "d9e", "e9e", "f9e",
  "0ae", "1ae", "2ae", "3ae", "4ae", "5ae", "6ae", "7ae",
  "8ae", "9ae", "aae", "bae", "cae", "dae", "eae", "fae",
  "0be", "1be", "2be", "3be", "4be", "5be", "6be", "7be",
  "8be", "9be", "abe", "bbe", "cbe", "dbe", "ebe", "fbe",
  "0ce", "1ce", "2ce", "3ce", "4ce", "5ce", "6ce", "7ce",
  "8ce", "9ce", "ace", "bce", "cce", "dce", "ece", "fce",
  "0de", "1de", "2de", "3de", "4de", "5de", "6de", "7de",
  "8de", "9de", "ade", "bde", "cde", "dde", "ede", "fde",
  "0ee", "1ee", "2ee", "3ee", "4ee", "5ee", "6ee", "7ee",
  "8ee", "9ee", "aee", "bee", "cee", "dee", "eee", "fee",
  "0fe", "1fe", "2fe", "3fe", "4fe", "5fe", "6fe", "7fe",
  "8fe", "9fe", "afe", "bfe", "cfe", "dfe", "efe", "ffe",
  "00f", "10f", "20f", "30f", "40f", "50f", "60f", "70f",
  "80f", "90f", "a0f", "b0f", "c0f", "d0f", "e0f", "f0f",
  "01f", "11f", "21f", "31f", "41f", "51f", "61f", "71f",
  "81f", "91f", "a1f", "b1f", "c1f", "d1f", "e1f", "f1f",
  "02f", "12f", "22f", "32f", "42f", "52f", "62f", "72f",
  "82f", "92f", "a2f", "b2f", "c2f", "d2f", "e2f", "f2f",
  "03f", "13f", "23f", "33f", "43f", "53f", "63f", "73f",
  "83f", "93f", "a3f", "b3f", "c3f", "d3f", "e3f", "f3f",
  "04f", "14f", "24f", "34f", "44f", "54f", "64f", "74f",
  "84f", "94f", "a4f", "b4f", "c4f", "d4f", "e4f", "f4f",
  "05f", "15f", "25f", "35f", "45f", "55f", "65f", "75f",
  "85f", "95f", "a5f", "b5f", "c5f", "d5f", "e5f", "f5f",
  "06f", "16f", "26f", "36f", "46f", "56f", "66f", "76f",
  "86f", "96f", "a6f", "b6f", "c6f", "d6f", "e6f", "f6f",
  "07f", "17f", "27f", "37f", "47f", "57f", "67f", "77f",
  "87f", "97f", "a7f", "b7f", "c7f", "d7f", "e7f", "f7f",
  "08f", "18f", "28f", "38f", "48f", "58f", "68f", "78f",
  "88f", "98f", "a8f", "b8f", "c8f", "d8f", "e8f", "f8f",
  "09f", "19f", "29f", "39f", "49f", "59f", "69f", "79f",
  "89f", "99f", "a9f", "b9f", "c9f", "d9f", "e9f", "f9f",
  "0af", "1af", "2af", "3af", "4af", "5af", "6af", "7af",
  "8af", "9af", "aaf", "baf", "caf", "daf", "eaf", "faf",
  "0bf", "1bf", "2bf", "3bf", "4bf", "5bf", "6bf", "7bf",
  "8bf", "9bf", "abf", "bbf", "cbf", "dbf", "ebf", "fbf",
  "0cf", "1cf", "2cf", "3cf", "4cf", "5cf", "6cf", "7cf",
  "8cf", "9cf", "acf", "bcf", "ccf", "dcf", "ecf", "fcf",
  "0df", "1df", "2df", "3df", "4df", "5df", "6df", "7df",
  "8df", "9df", "adf", "bdf", "cdf", "ddf", "edf", "fdf",
  "0ef", "1ef", "2ef", "3ef", "4ef", "5ef", "6ef", "7ef",
  "8ef", "9ef", "aef", "bef", "cef", "def", "eef", "fef",
  "0ff", "1ff", "2ff", "3ff", "4ff", "5ff", "6ff", "7ff",
  "8ff", "9ff", "aff", "bff", "cff", "dff", "eff", "fff"
};

/** string table for upper-case hexadecimal values */
static char *HEX[] = {
     "",   "1",   "2",   "3",   "4",   "5",   "6",   "7",
    "8",   "9",   "A",   "B",   "C",   "D",   "E",   "F",
   "01",  "11",  "21",  "31",  "41",  "51",  "61",  "71",
   "81",  "91",  "A1",  "B1",  "C1",  "D1",  "E1",  "F1",
   "02",  "12",  "22",  "32",  "42",  "52",  "62",  "72",
   "82",  "92",  "A2",  "B2",  "C2",  "D2",  "E2",  "F2",
   "03",  "13",  "23",  "33",  "43",  "53",  "63",  "73",
   "83",  "93",  "A3",  "B3",  "C3",  "D3",  "E3",  "F3",
   "04",  "14",  "24",  "34",  "44",  "54",  "64",  "74",
   "84",  "94",  "A4",  "B4",  "C4",  "D4",  "E4",  "F4",
   "05",  "15",  "25",  "35",  "45",  "55",  "65",  "75",
   "85",  "95",  "A5",  "B5",  "C5",  "D5",  "E5",  "F5",
   "06",  "16",  "26",  "36",  "46",  "56",  "66",  "76",
   "86",  "96",  "A6",  "B6",  "C6",  "D6",  "E6",  "F6",
   "07",  "17",  "27",  "37",  "47",  "57",  "67",  "77",
   "87",  "97",  "A7",  "B7",  "C7",  "D7",  "E7",  "F7",
   "08",  "18",  "28",  "38",  "48",  "58",  "68",  "78",
   "88",  "98",  "A8",  "B8",  "C8",  "D8",  "E8",  "F8",
   "09",  "19",  "29",  "39",  "49",  "59",  "69",  "79",
   "89",  "99",  "A9",  "B9",  "C9",  "D9",  "E9",  "F9",
   "0A",  "1A",  "2A",  "3A",  "4A",  "5A",  "6A",  "7A",
   "8A",  "9A",  "AA",  "BA",  "CA",  "DA",  "EA",  "FA",
   "0B",  "1B",  "2B",  "3B",  "4B",  "5B",  "6B",  "7B",
   "8B",  "9B",  "AB",  "BB",  "CB",  "DB",  "EB",  "FB",
   "0C",  "1C",  "2C",  "3C",  "4C",  "5C",  "6C",  "7C",
   "8C",  "9C",  "AC",  "BC",  "CC",  "DC",  "EC",  "FC",
   "0D",  "1D",  "2D",  "3D",  "4D",  "5D",  "6D",  "7D",
   "8D",  "9D",  "AD",  "BD",  "CD",  "DD",  "ED",  "FD",
   "0E",  "1E",  "2E",  "3E",  "4E",  "5E",  "6E",  "7E",
   "8E",  "9E",  "AE",  "BE",  "CE",  "DE",  "EE",  "FE",
   "0F",  "1F",  "2F",  "3F",  "4F",  "5F",  "6F",  "7F",
   "8F",  "9F",  "AF",  "BF",  "CF",  "DF",  "EF",  "FF",
  "001", "101", "201", "301", "401", "501", "601", "701",
  "801", "901", "A01", "B01", "C01", "D01", "E01", "F01",
  "011", "111", "211", "311", "411", "511", "611", "711",
  "811", "911", "A11", "B11", "C11", "D11", "E11", "F11",
  "021", "121", "221", "321", "421", "521", "621", "721",
  "821", "921", "A21", "B21", "C21", "D21", "E21", "F21",
  "031", "131", "231", "331", "431", "531", "631", "731",
  "831", "931", "A31", "B31", "C31", "D31", "E31", "F31",
  "041", "141", "241", "341", "441", "541", "641", "741",
  "841", "941", "A41", "B41", "C41", "D41", "E41", "F41",
  "051", "151", "251", "351", "451", "551", "651", "751",
  "851", "951", "A51", "B51", "C51", "D51", "E51", "F51",
  "061", "161", "261", "361", "461", "561", "661", "761",
  "861", "961", "A61", "B61", "C61", "D61", "E61", "F61",
  "071", "171", "271", "371", "471", "571", "671", "771",
  "871", "971", "A71", "B71", "C71", "D71", "E71", "F71",
  "081", "181", "281", "381", "481", "581", "681", "781",
  "881", "981", "A81", "B81", "C81", "D81", "E81", "F81",
  "091", "191", "291", "391", "491", "591", "691", "791",
  "891", "991", "A91", "B91", "C91", "D91", "E91", "F91",
  "0A1", "1A1", "2A1", "3A1", "4A1", "5A1", "6A1", "7A1",
  "8A1", "9A1", "AA1", "BA1", "CA1", "DA1", "EA1", "FA1",
  "0B1", "1B1", "2B1", "3B1", "4B1", "5B1", "6B1", "7B1",
  "8B1", "9B1", "AB1", "BB1", "CB1", "DB1", "EB1", "FB1",
  "0C1", "1C1", "2C1", "3C1", "4C1", "5C1", "6C1", "7C1",
  "8C1", "9C1", "AC1", "BC1", "CC1", "DC1", "EC1", "FC1",
  "0D1", "1D1", "2D1", "3D1", "4D1", "5D1", "6D1", "7D1",
  "8D1", "9D1", "AD1", "BD1", "CD1", "DD1", "ED1", "FD1",
  "0E1", "1E1", "2E1", "3E1", "4E1", "5E1", "6E1", "7E1",
  "8E1", "9E1", "AE1", "BE1", "CE1", "DE1", "EE1", "FE1",
  "0F1", "1F1", "2F1", "3F1", "4F1", "5F1", "6F1", "7F1",
  "8F1", "9F1", "AF1", "BF1", "CF1", "DF1", "EF1", "FF1",
  "002", "102", "202", "302", "402", "502", "602", "702",
  "802", "902", "A02", "B02", "C02", "D02", "E02", "F02",
  "012", "112", "212", "312", "412", "512", "612", "712",
  "812", "912", "A12", "B12", "C12", "D12", "E12", "F12",
  "022", "122", "222", "322", "422", "522", "622", "722",
  "822", "922", "A22", "B22", "C22", "D22", "E22", "F22",
  "032", "132", "232", "332", "432", "532", "632", "732",
  "832", "932", "A32", "B32", "C32", "D32", "E32", "F32",
  "042", "142", "242", "342", "442", "542", "642", "742",
  "842", "942", "A42", "B42", "C42", "D42", "E42", "F42",
  "052", "152", "252", "352", "452", "552", "652", "752",
  "852", "952", "A52", "B52", "C52", "D52", "E52", "F52",
  "062", "162", "262", "362", "462", "562", "662", "762",
  "862", "962", "A62", "B62", "C62", "D62", "E62", "F62",
  "072", "172", "272", "372", "472", "572", "672", "772",
  "872", "972", "A72", "B72", "C72", "D72", "E72", "F72",
  "082", "182", "282", "382", "482", "582", "682", "782",
  "882", "982", "A82", "B82", "C82", "D82", "E82", "F82",
  "092", "192", "292", "392", "492", "592", "692", "792",
  "892", "992", "A92", "B92", "C92", "D92", "E92", "F92",
  "0A2", "1A2", "2A2", "3A2", "4A2", "5A2", "6A2", "7A2",
  "8A2", "9A2", "AA2", "BA2", "CA2", "DA2", "EA2", "FA2",
  "0B2", "1B2", "2B2", "3B2", "4B2", "5B2", "6B2", "7B2",
  "8B2", "9B2", "AB2", "BB2", "CB2", "DB2", "EB2", "FB2",
  "0C2", "1C2", "2C2", "3C2", "4C2", "5C2", "6C2", "7C2",
  "8C2", "9C2", "AC2", "BC2", "CC2", "DC2", "EC2", "FC2",
  "0D2", "1D2", "2D2", "3D2", "4D2", "5D2", "6D2", "7D2",
  "8D2", "9D2", "AD2", "BD2", "CD2", "DD2", "ED2", "FD2",
  "0E2", "1E2", "2E2", "3E2", "4E2", "5E2", "6E2", "7E2",
  "8E2", "9E2", "AE2", "BE2", "CE2", "DE2", "EE2", "FE2",
  "0F2", "1F2", "2F2", "3F2", "4F2", "5F2", "6F2", "7F2",
  "8F2", "9F2", "AF2", "BF2", "CF2", "DF2", "EF2", "FF2",
  "003", "103", "203", "303", "403", "503", "603", "703",
  "803", "903", "A03", "B03", "C03", "D03", "E03", "F03",
  "013", "113", "213", "313", "413", "513", "613", "713",
  "813", "913", "A13", "B13", "C13", "D13", "E13", "F13",
  "023", "123", "223", "323", "423", "523", "623", "723",
  "823", "923", "A23", "B23", "C23", "D23", "E23", "F23",
  "033", "133", "233", "333", "433", "533", "633", "733",
  "833", "933", "A33", "B33", "C33", "D33", "E33", "F33",
  "043", "143", "243", "343", "443", "543", "643", "743",
  "843", "943", "A43", "B43", "C43", "D43", "E43", "F43",
  "053", "153", "253", "353", "453", "553", "653", "753",
  "853", "953", "A53", "B53", "C53", "D53", "E53", "F53",
  "063", "163", "263", "363", "463", "563", "663", "763",
  "863", "963", "A63", "B63", "C63", "D63", "E63", "F63",
  "073", "173", "273", "373", "473", "573", "673", "773",
  "873", "973", "A73", "B73", "C73", "D73", "E73", "F73",
  "083", "183", "283", "383", "483", "583", "683", "783",
  "883", "983", "A83", "B83", "C83", "D83", "E83", "F83",
  "093", "193", "293", "393", "493", "593", "693", "793",
  "893", "993", "A93", "B93", "C93", "D93", "E93", "F93",
  "0A3", "1A3", "2A3", "3A3", "4A3", "5A3", "6A3", "7A3",
  "8A3", "9A3", "AA3", "BA3", "CA3", "DA3", "EA3", "FA3",
  "0B3", "1B3", "2B3", "3B3", "4B3", "5B3", "6B3", "7B3",
  "8B3", "9B3", "AB3", "BB3", "CB3", "DB3", "EB3", "FB3",
  "0C3", "1C3", "2C3", "3C3", "4C3", "5C3", "6C3", "7C3",
  "8C3", "9C3", "AC3", "BC3", "CC3", "DC3", "EC3", "FC3",
  "0D3", "1D3", "2D3", "3D3", "4D3", "5D3", "6D3", "7D3",
  "8D3", "9D3", "AD3", "BD3", "CD3", "DD3", "ED3", "FD3",
  "0E3", "1E3", "2E3", "3E3", "4E3", "5E3", "6E3", "7E3",
  "8E3", "9E3", "AE3", "BE3", "CE3", "DE3", "EE3", "FE3",
  "0F3", "1F3", "2F3", "3F3", "4F3", "5F3", "6F3", "7F3",
  "8F3", "9F3", "AF3", "BF3", "CF3", "DF3", "EF3", "FF3",
  "004", "104", "204", "304", "404", "504", "604", "704",
  "804", "904", "A04", "B04", "C04", "D04", "E04", "F04",
  "014", "114", "214", "314", "414", "514", "614", "714",
  "814", "914", "A14", "B14", "C14", "D14", "E14", "F14",
  "024", "124", "224", "324", "424", "524", "624", "724",
  "824", "924", "A24", "B24", "C24", "D24", "E24", "F24",
  "034", "134", "234", "334", "434", "534", "634", "734",
  "834", "934", "A34", "B34", "C34", "D34", "E34", "F34",
  "044", "144", "244", "344", "444", "544", "644", "744",
  "844", "944", "A44", "B44", "C44", "D44", "E44", "F44",
  "054", "154", "254", "354", "454", "554", "654", "754",
  "854", "954", "A54", "B54", "C54", "D54", "E54", "F54",
  "064", "164", "264", "364", "464", "564", "664", "764",
  "864", "964", "A64", "B64", "C64", "D64", "E64", "F64",
  "074", "174", "274", "374", "474", "574", "674", "774",
  "874", "974", "A74", "B74", "C74", "D74", "E74", "F74",
  "084", "184", "284", "384", "484", "584", "684", "784",
  "884", "984", "A84", "B84", "C84", "D84", "E84", "F84",
  "094", "194", "294", "394", "494", "594", "694", "794",
  "894", "994", "A94", "B94", "C94", "D94", "E94", "F94",
  "0A4", "1A4", "2A4", "3A4", "4A4", "5A4", "6A4", "7A4",
  "8A4", "9A4", "AA4", "BA4", "CA4", "DA4", "EA4", "FA4",
  "0B4", "1B4", "2B4", "3B4", "4B4", "5B4", "6B4", "7B4",
  "8B4", "9B4", "AB4", "BB4", "CB4", "DB4", "EB4", "FB4",
  "0C4", "1C4", "2C4", "3C4", "4C4", "5C4", "6C4", "7C4",
  "8C4", "9C4", "AC4", "BC4", "CC4", "DC4", "EC4", "FC4",
  "0D4", "1D4", "2D4", "3D4", "4D4", "5D4", "6D4", "7D4",
  "8D4", "9D4", "AD4", "BD4", "CD4", "DD4", "ED4", "FD4",
  "0E4", "1E4", "2E4", "3E4", "4E4", "5E4", "6E4", "7E4",
  "8E4", "9E4", "AE4", "BE4", "CE4", "DE4", "EE4", "FE4",
  "0F4", "1F4", "2F4", "3F4", "4F4", "5F4", "6F4", "7F4",
  "8F4", "9F4", "AF4", "BF4", "CF4", "DF4", "EF4", "FF4",
  "005", "105", "205", "305", "405", "505", "605", "705",
  "805", "905", "A05", "B05", "C05", "D05", "E05", "F05",
  "015", "115", "215", "315", "415", "515", "615", "715",
  "815", "915", "A15", "B15", "C15", "D15", "E15", "F15",
  "025", "125", "225", "325", "425", "525", "625", "725",
  "825", "925", "A25", "B25", "C25", "D25", "E25", "F25",
  "035", "135", "235", "335", "435", "535", "635", "735",
  "835", "935", "A35", "B35", "C35", "D35", "E35", "F35",
  "045", "145", "245", "345", "445", "545", "645", "745",
  "845", "945", "A45", "B45", "C45", "D45", "E45", "F45",
  "055", "155", "255", "355", "455", "555", "655", "755",
  "855", "955", "A55", "B55", "C55", "D55", "E55", "F55",
  "065", "165", "265", "365", "465", "565", "665", "765",
  "865", "965", "A65", "B65", "C65", "D65", "E65", "F65",
  "075", "175", "275", "375", "475", "575", "675", "775",
  "875", "975", "A75", "B75", "C75", "D75", "E75", "F75",
  "085", "185", "285", "385", "485", "585", "685", "785",
  "885", "985", "A85", "B85", "C85", "D85", "E85", "F85",
  "095", "195", "295", "395", "495", "595", "695", "795",
  "895", "995", "A95", "B95", "C95", "D95", "E95", "F95",
  "0A5", "1A5", "2A5", "3A5", "4A5", "5A5", "6A5", "7A5",
  "8A5", "9A5", "AA5", "BA5", "CA5", "DA5", "EA5", "FA5",
  "0B5", "1B5", "2B5", "3B5", "4B5", "5B5", "6B5", "7B5",
  "8B5", "9B5", "AB5", "BB5", "CB5", "DB5", "EB5", "FB5",
  "0C5", "1C5", "2C5", "3C5", "4C5", "5C5", "6C5", "7C5",
  "8C5", "9C5", "AC5", "BC5", "CC5", "DC5", "EC5", "FC5",
  "0D5", "1D5", "2D5", "3D5", "4D5", "5D5", "6D5", "7D5",
  "8D5", "9D5", "AD5", "BD5", "CD5", "DD5", "ED5", "FD5",
  "0E5", "1E5", "2E5", "3E5", "4E5", "5E5", "6E5", "7E5",
  "8E5", "9E5", "AE5", "BE5", "CE5", "DE5", "EE5", "FE5",
  "0F5", "1F5", "2F5", "3F5", "4F5", "5F5", "6F5", "7F5",
  "8F5", "9F5", "AF5", "BF5", "CF5", "DF5", "EF5", "FF5",
  "006", "106", "206", "306", "406", "506", "606", "706",
  "806", "906", "A06", "B06", "C06", "D06", "E06", "F06",
  "016", "116", "216", "316", "416", "516", "616", "716",
  "816", "916", "A16", "B16", "C16", "D16", "E16", "F16",
  "026", "126", "226", "326", "426", "526", "626", "726",
  "826", "926", "A26", "B26", "C26", "D26", "E26", "F26",
  "036", "136", "236", "336", "436", "536", "636", "736",
  "836", "936", "A36", "B36", "C36", "D36", "E36", "F36",
  "046", "146", "246", "346", "446", "546", "646", "746",
  "846", "946", "A46", "B46", "C46", "D46", "E46", "F46",
  "056", "156", "256", "356", "456", "556", "656", "756",
  "856", "956", "A56", "B56", "C56", "D56", "E56", "F56",
  "066", "166", "266", "366", "466", "566", "666", "766",
  "866", "966", "A66", "B66", "C66", "D66", "E66", "F66",
  "076", "176", "276", "376", "476", "576", "676", "776",
  "876", "976", "A76", "B76", "C76", "D76", "E76", "F76",
  "086", "186", "286", "386", "486", "586", "686", "786",
  "886", "986", "A86", "B86", "C86", "D86", "E86", "F86",
  "096", "196", "296", "396", "496", "596", "696", "796",
  "896", "996", "A96", "B96", "C96", "D96", "E96", "F96",
  "0A6", "1A6", "2A6", "3A6", "4A6", "5A6", "6A6", "7A6",
  "8A6", "9A6", "AA6", "BA6", "CA6", "DA6", "EA6", "FA6",
  "0B6", "1B6", "2B6", "3B6", "4B6", "5B6", "6B6", "7B6",
  "8B6", "9B6", "AB6", "BB6", "CB6", "DB6", "EB6", "FB6",
  "0C6", "1C6", "2C6", "3C6", "4C6", "5C6", "6C6", "7C6",
  "8C6", "9C6", "AC6", "BC6", "CC6", "DC6", "EC6", "FC6",
  "0D6", "1D6", "2D6", "3D6", "4D6", "5D6", "6D6", "7D6",
  "8D6", "9D6", "AD6", "BD6", "CD6", "DD6", "ED6", "FD6",
  "0E6", "1E6", "2E6", "3E6", "4E6", "5E6", "6E6", "7E6",
  "8E6", "9E6", "AE6", "BE6", "CE6", "DE6", "EE6", "FE6",
  "0F6", "1F6", "2F6", "3F6", "4F6", "5F6", "6F6", "7F6",
  "8F6", "9F6", "AF6", "BF6", "CF6", "DF6", "EF6", "FF6",
  "007", "107", "207", "307", "407", "507", "607", "707",
  "807", "907", "A07", "B07", "C07", "D07", "E07", "F07",
  "017", "117", "217", "317", "417", "517", "617", "717",
  "817", "917", "A17", "B17", "C17", "D17", "E17", "F17",
  "027", "127", "227", "327", "427", "527", "627", "727",
  "827", "927", "A27", "B27", "C27", "D27", "E27", "F27",
  "037", "137", "237", "337", "437", "537", "637", "737",
  "837", "937", "A37", "B37", "C37", "D37", "E37", "F37",
  "047", "147", "247", "347", "447", "547", "647", "747",
  "847", "947", "A47", "B47", "C47", "D47", "E47", "F47",
  "057", "157", "257", "357", "457", "557", "657", "757",
  "857", "957", "A57", "B57", "C57", "D57", "E57", "F57",
  "067", "167", "267", "367", "467", "567", "667", "767",
  "867", "967", "A67", "B67", "C67", "D67", "E67", "F67",
  "077", "177", "277", "377", "477", "577", "677", "777",
  "877", "977", "A77", "B77", "C77", "D77", "E77", "F77",
  "087", "187", "287", "387", "487", "587", "687", "787",
  "887", "987", "A87", "B87", "C87", "D87", "E87", "F87",
  "097", "197", "297", "397", "497", "597", "697", "797",
  "897", "997", "A97", "B97", "C97", "D97", "E97", "F97",
  "0A7", "1A7", "2A7", "3A7", "4A7", "5A7", "6A7", "7A7",
  "8A7", "9A7", "AA7", "BA7", "CA7", "DA7", "EA7", "FA7",
  "0B7", "1B7", "2B7", "3B7", "4B7", "5B7", "6B7", "7B7",
  "8B7", "9B7", "AB7", "BB7", "CB7", "DB7", "EB7", "FB7",
  "0C7", "1C7", "2C7", "3C7", "4C7", "5C7", "6C7", "7C7",
  "8C7", "9C7", "AC7", "BC7", "CC7", "DC7", "EC7", "FC7",
  "0D7", "1D7", "2D7", "3D7", "4D7", "5D7", "6D7", "7D7",
  "8D7", "9D7", "AD7", "BD7", "CD7", "DD7", "ED7", "FD7",
  "0E7", "1E7", "2E7", "3E7", "4E7", "5E7", "6E7", "7E7",
  "8E7", "9E7", "AE7", "BE7", "CE7", "DE7", "EE7", "FE7",
  "0F7", "1F7", "2F7", "3F7", "4F7", "5F7", "6F7", "7F7",
  "8F7", "9F7", "AF7", "BF7", "CF7", "DF7", "EF7", "FF7",
  "008", "108", "208", "308", "408", "508", "608", "708",
  "808", "908", "A08", "B08", "C08", "D08", "E08", "F08",
  "018", "118", "218", "318", "418", "518", "618", "718",
  "818", "918", "A18", "B18", "C18", "D18", "E18", "F18",
  "028", "128", "228", "328", "428", "528", "628", "728",
  "828", "928", "A28", "B28", "C28", "D28", "E28", "F28",
  "038", "138", "238", "338", "438", "538", "638", "738",
  "838", "938", "A38", "B38", "C38", "D38", "E38", "F38",
  "048", "148", "248", "348", "448", "548", "648", "748",
  "848", "948", "A48", "B48", "C48", "D48", "E48", "F48",
  "058", "158", "258", "358", "458", "558", "658", "758",
  "858", "958", "A58", "B58", "C58", "D58", "E58", "F58",
  "068", "168", "268", "368", "468", "568", "668", "768",
  "868", "968", "A68", "B68", "C68", "D68", "E68", "F68",
  "078", "178", "278", "378", "478", "578", "678", "778",
  "878", "978", "A78", "B78", "C78", "D78", "E78", "F78",
  "088", "188", "288", "388", "488", "588", "688", "788",
  "888", "988", "A88", "B88", "C88", "D88", "E88", "F88",
  "098", "198", "298", "398", "498", "598", "698", "798",
  "898", "998", "A98", "B98", "C98", "D98", "E98", "F98",
  "0A8", "1A8", "2A8", "3A8", "4A8", "5A8", "6A8", "7A8",
  "8A8", "9A8", "AA8", "BA8", "CA8", "DA8", "EA8", "FA8",
  "0B8", "1B8", "2B8", "3B8", "4B8", "5B8", "6B8", "7B8",
  "8B8", "9B8", "AB8", "BB8", "CB8", "DB8", "EB8", "FB8",
  "0C8", "1C8", "2C8", "3C8", "4C8", "5C8", "6C8", "7C8",
  "8C8", "9C8", "AC8", "BC8", "CC8", "DC8", "EC8", "FC8",
  "0D8", "1D8", "2D8", "3D8", "4D8", "5D8", "6D8", "7D8",
  "8D8", "9D8", "AD8", "BD8", "CD8", "DD8", "ED8", "FD8",
  "0E8", "1E8", "2E8", "3E8", "4E8", "5E8", "6E8", "7E8",
  "8E8", "9E8", "AE8", "BE8", "CE8", "DE8", "EE8", "FE8",
  "0F8", "1F8", "2F8", "3F8", "4F8", "5F8", "6F8", "7F8",
  "8F8", "9F8", "AF8", "BF8", "CF8", "DF8", "EF8", "FF8",
  "009", "109", "209", "309", "409", "509", "609", "709",
  "809", "909", "A09", "B09", "C09", "D09", "E09", "F09",
  "019", "119", "219", "319", "419", "519", "619", "719",
  "819", "919", "A19", "B19", "C19", "D19", "E19", "F19",
  "029", "129", "229", "329", "429", "529", "629", "729",
  "829", "929", "A29", "B29", "C29", "D29", "E29", "F29",
  "039", "139", "239", "339", "439", "539", "639", "739",
  "839", "939", "A39", "B39", "C39", "D39", "E39", "F39",
  "049", "149", "249", "349", "449", "549", "649", "749",
  "849", "949", "A49", "B49", "C49", "D49", "E49", "F49",
  "059", "159", "259", "359", "459", "559", "659", "759",
  "859", "959", "A59", "B59", "C59", "D59", "E59", "F59",
  "069", "169", "269", "369", "469", "569", "669", "769",
  "869", "969", "A69", "B69", "C69", "D69", "E69", "F69",
  "079", "179", "279", "379", "479", "579", "679", "779",
  "879", "979", "A79", "B79", "C79", "D79", "E79", "F79",
  "089", "189", "289", "389", "489", "589", "689", "789",
  "889", "989", "A89", "B89", "C89", "D89", "E89", "F89",
  "099", "199", "299", "399", "499", "599", "699", "799",
  "899", "999", "A99", "B99", "C99", "D99", "E99", "F99",
  "0A9", "1A9", "2A9", "3A9", "4A9", "5A9", "6A9", "7A9",
  "8A9", "9A9", "AA9", "BA9", "CA9", "DA9", "EA9", "FA9",
  "0B9", "1B9", "2B9", "3B9", "4B9", "5B9", "6B9", "7B9",
  "8B9", "9B9", "AB9", "BB9", "CB9", "DB9", "EB9", "FB9",
  "0C9", "1C9", "2C9", "3C9", "4C9", "5C9", "6C9", "7C9",
  "8C9", "9C9", "AC9", "BC9", "CC9", "DC9", "EC9", "FC9",
  "0D9", "1D9", "2D9", "3D9", "4D9", "5D9", "6D9", "7D9",
  "8D9", "9D9", "AD9", "BD9", "CD9", "DD9", "ED9", "FD9",
  "0E9", "1E9", "2E9", "3E9", "4E9", "5E9", "6E9", "7E9",
  "8E9", "9E9", "AE9", "BE9", "CE9", "DE9", "EE9", "FE9",
  "0F9", "1F9", "2F9", "3F9", "4F9", "5F9", "6F9", "7F9",
  "8F9", "9F9", "AF9", "BF9", "CF9", "DF9", "EF9", "FF9",
  "00A", "10A", "20A", "30A", "40A", "50A", "60A", "70A",
  "80A", "90A", "A0A", "B0A", "C0A", "D0A", "E0A", "F0A",
  "01A", "11A", "21A", "31A", "41A", "51A", "61A", "71A",
  "81A", "91A", "A1A", "B1A", "C1A", "D1A", "E1A", "F1A",
  "02A", "12A", "22A", "32A", "42A", "52A", "62A", "72A",
  "82A", "92A", "A2A", "B2A", "C2A", "D2A", "E2A", "F2A",
  "03A", "13A", "23A", "33A", "43A", "53A", "63A", "73A",
  "83A", "93A", "A3A", "B3A", "C3A", "D3A", "E3A", "F3A",
  "04A", "14A", "24A", "34A", "44A", "54A", "64A", "74A",
  "84A", "94A", "A4A", "B4A", "C4A", "D4A", "E4A", "F4A",
  "05A", "15A", "25A", "35A", "45A", "55A", "65A", "75A",
  "85A", "95A", "A5A", "B5A", "C5A", "D5A", "E5A", "F5A",
  "06A", "16A", "26A", "36A", "46A", "56A", "66A", "76A",
  "86A", "96A", "A6A", "B6A", "C6A", "D6A", "E6A", "F6A",
  "07A", "17A", "27A", "37A", "47A", "57A", "67A", "77A",
  "87A", "97A", "A7A", "B7A", "C7A", "D7A", "E7A", "F7A",
  "08A", "18A", "28A", "38A", "48A", "58A", "68A", "78A",
  "88A", "98A", "A8A", "B8A", "C8A", "D8A", "E8A", "F8A",
  "09A", "19A", "29A", "39A", "49A", "59A", "69A", "79A",
  "89A", "99A", "A9A", "B9A", "C9A", "D9A", "E9A", "F9A",
  "0AA", "1AA", "2AA", "3AA", "4AA", "5AA", "6AA", "7AA",
  "8AA", "9AA", "AAA", "BAA", "CAA", "DAA", "EAA", "FAA",
  "0BA", "1BA", "2BA", "3BA", "4BA", "5BA", "6BA", "7BA",
  "8BA", "9BA", "ABA", "BBA", "CBA", "DBA", "EBA", "FBA",
  "0CA", "1CA", "2CA", "3CA", "4CA", "5CA", "6CA", "7CA",
  "8CA", "9CA", "ACA", "BCA", "CCA", "DCA", "ECA", "FCA",
  "0DA", "1DA", "2DA", "3DA", "4DA", "5DA", "6DA", "7DA",
  "8DA", "9DA", "ADA", "BDA", "CDA", "DDA", "EDA", "FDA",
  "0EA", "1EA", "2EA", "3EA", "4EA", "5EA", "6EA", "7EA",
  "8EA", "9EA", "AEA", "BEA", "CEA", "DEA", "EEA", "FEA",
  "0FA", "1FA", "2FA", "3FA", "4FA", "5FA", "6FA", "7FA",
  "8FA", "9FA", "AFA", "BFA", "CFA", "DFA", "EFA", "FFA",
  "00B", "10B", "20B", "30B", "40B", "50B", "60B", "70B",
  "80B", "90B", "A0B", "B0B", "C0B", "D0B", "E0B", "F0B",
  "01B", "11B", "21B", "31B", "41B", "51B", "61B", "71B",
  "81B", "91B", "A1B", "B1B", "C1B", "D1B", "E1B", "F1B",
  "02B", "12B", "22B", "32B", "42B", "52B", "62B", "72B",
  "82B", "92B", "A2B", "B2B", "C2B", "D2B", "E2B", "F2B",
  "03B", "13B", "23B", "33B", "43B", "53B", "63B", "73B",
  "83B", "93B", "A3B", "B3B", "C3B", "D3B", "E3B", "F3B",
  "04B", "14B", "24B", "34B", "44B", "54B", "64B", "74B",
  "84B", "94B", "A4B", "B4B", "C4B", "D4B", "E4B", "F4B",
  "05B", "15B", "25B", "35B", "45B", "55B", "65B", "75B",
  "85B", "95B", "A5B", "B5B", "C5B", "D5B", "E5B", "F5B",
  "06B", "16B", "26B", "36B", "46B", "56B", "66B", "76B",
  "86B", "96B", "A6B", "B6B", "C6B", "D6B", "E6B", "F6B",
  "07B", "17B", "27B", "37B", "47B", "57B", "67B", "77B",
  "87B", "97B", "A7B", "B7B", "C7B", "D7B", "E7B", "F7B",
  "08B", "18B", "28B", "38B", "48B", "58B", "68B", "78B",
  "88B", "98B", "A8B", "B8B", "C8B", "D8B", "E8B", "F8B",
  "09B", "19B", "29B", "39B", "49B", "59B", "69B", "79B",
  "89B", "99B", "A9B", "B9B", "C9B", "D9B", "E9B", "F9B",
  "0AB", "1AB", "2AB", "3AB", "4AB", "5AB", "6AB", "7AB",
  "8AB", "9AB", "AAB", "BAB", "CAB", "DAB", "EAB", "FAB",
  "0BB", "1BB", "2BB", "3BB", "4BB", "5BB", "6BB", "7BB",
  "8BB", "9BB", "ABB", "BBB", "CBB", "DBB", "EBB", "FBB",
  "0CB", "1CB", "2CB", "3CB", "4CB", "5CB", "6CB", "7CB",
  "8CB", "9CB", "ACB", "BCB", "CCB", "DCB", "ECB", "FCB",
  "0DB", "1DB", "2DB", "3DB", "4DB", "5DB", "6DB", "7DB",
  "8DB", "9DB", "ADB", "BDB", "CDB", "DDB", "EDB", "FDB",
  "0EB", "1EB", "2EB", "3EB", "4EB", "5EB", "6EB", "7EB",
  "8EB", "9EB", "AEB", "BEB", "CEB", "DEB", "EEB", "FEB",
  "0FB", "1FB", "2FB", "3FB", "4FB", "5FB", "6FB", "7FB",
  "8FB", "9FB", "AFB", "BFB", "CFB", "DFB", "EFB", "FFB",
  "00C", "10C", "20C", "30C", "40C", "50C", "60C", "70C",
  "80C", "90C", "A0C", "B0C", "C0C", "D0C", "E0C", "F0C",
  "01C", "11C", "21C", "31C", "41C", "51C", "61C", "71C",
  "81C", "91C", "A1C", "B1C", "C1C", "D1C", "E1C", "F1C",
  "02C", "12C", "22C", "32C", "42C", "52C", "62C", "72C",
  "82C", "92C", "A2C", "B2C", "C2C", "D2C", "E2C", "F2C",
  "03C", "13C", "23C", "33C", "43C", "53C", "63C", "73C",
  "83C", "93C", "A3C", "B3C", "C3C", "D3C", "E3C", "F3C",
  "04C", "14C", "24C", "34C", "44C", "54C", "64C", "74C",
  "84C", "94C", "A4C", "B4C", "C4C", "D4C", "E4C", "F4C",
  "05C", "15C", "25C", "35C", "45C", "55C", "65C", "75C",
  "85C", "95C", "A5C", "B5C", "C5C", "D5C", "E5C", "F5C",
  "06C", "16C", "26C", "36C", "46C", "56C", "66C", "76C",
  "86C", "96C", "A6C", "B6C", "C6C", "D6C", "E6C", "F6C",
  "07C", "17C", "27C", "37C", "47C", "57C", "67C", "77C",
  "87C", "97C", "A7C", "B7C", "C7C", "D7C", "E7C", "F7C",
  "08C", "18C", "28C", "38C", "48C", "58C", "68C", "78C",
  "88C", "98C", "A8C", "B8C", "C8C", "D8C", "E8C", "F8C",
  "09C", "19C", "29C", "39C", "49C", "59C", "69C", "79C",
  "89C", "99C", "A9C", "B9C", "C9C", "D9C", "E9C", "F9C",
  "0AC", "1AC", "2AC", "3AC", "4AC", "5AC", "6AC", "7AC",
  "8AC", "9AC", "AAC", "BAC", "CAC", "DAC", "EAC", "FAC",
  "0BC", "1BC", "2BC", "3BC", "4BC", "5BC", "6BC", "7BC",
  "8BC", "9BC", "ABC", "BBC", "CBC", "DBC", "EBC", "FBC",
  "0CC", "1CC", "2CC", "3CC", "4CC", "5CC", "6CC", "7CC",
  "8CC", "9CC", "ACC", "BCC", "CCC", "DCC", "ECC", "FCC",
  "0DC", "1DC", "2DC", "3DC", "4DC", "5DC", "6DC", "7DC",
  "8DC", "9DC", "ADC", "BDC", "CDC", "DDC", "EDC", "FDC",
  "0EC", "1EC", "2EC", "3EC", "4EC", "5EC", "6EC", "7EC",
  "8EC", "9EC", "AEC", "BEC", "CEC", "DEC", "EEC", "FEC",
  "0FC", "1FC", "2FC", "3FC", "4FC", "5FC", "6FC", "7FC",
  "8FC", "9FC", "AFC", "BFC", "CFC", "DFC", "EFC", "FFC",
  "00D", "10D", "20D", "30D", "40D", "50D", "60D", "70D",
  "80D", "90D", "A0D", "B0D", "C0D", "D0D", "E0D", "F0D",
  "01D", "11D", "21D", "31D", "41D", "51D", "61D", "71D",
  "81D", "91D", "A1D", "B1D", "C1D", "D1D", "E1D", "F1D",
  "02D", "12D", "22D", "32D", "42D", "52D", "62D", "72D",
  "82D", "92D", "A2D", "B2D", "C2D", "D2D", "E2D", "F2D",
  "03D", "13D", "23D", "33D", "43D", "53D", "63D", "73D",
  "83D", "93D", "A3D", "B3D", "C3D", "D3D", "E3D", "F3D",
  "04D", "14D", "24D", "34D", "44D", "54D", "64D", "74D",
  "84D", "94D", "A4D", "B4D", "C4D", "D4D", "E4D", "F4D",
  "05D", "15D", "25D", "35D", "45D", "55D", "65D", "75D",
  "85D", "95D", "A5D", "B5D", "C5D", "D5D", "E5D", "F5D",
  "06D", "16D", "26D", "36D", "46D", "56D", "66D", "76D",
  "86D", "96D", "A6D", "B6D", "C6D", "D6D", "E6D", "F6D",
  "07D", "17D", "27D", "37D", "47D", "57D", "67D", "77D",
  "87D", "97D", "A7D", "B7D", "C7D", "D7D", "E7D", "F7D",
  "08D", "18D", "28D", "38D", "48D", "58D", "68D", "78D",
  "88D", "98D", "A8D", "B8D", "C8D", "D8D", "E8D", "F8D",
  "09D", "19D", "29D", "39D", "49D", "59D", "69D", "79D",
  "89D", "99D", "A9D", "B9D", "C9D", "D9D", "E9D", "F9D",
  "0AD", "1AD", "2AD", "3AD", "4AD", "5AD", "6AD", "7AD",
  "8AD", "9AD", "AAD", "BAD", "CAD", "DAD", "EAD", "FAD",
  "0BD", "1BD", "2BD", "3BD", "4BD", "5BD", "6BD", "7BD",
  "8BD", "9BD", "ABD", "BBD", "CBD", "DBD", "EBD", "FBD",
  "0CD", "1CD", "2CD", "3CD", "4CD", "5CD", "6CD", "7CD",
  "8CD", "9CD", "ACD", "BCD", "CCD", "DCD", "ECD", "FCD",
  "0DD", "1DD", "2DD", "3DD", "4DD", "5DD", "6DD", "7DD",
  "8DD", "9DD", "ADD", "BDD", "CDD", "DDD", "EDD", "FDD",
  "0ED", "1ED", "2ED", "3ED", "4ED", "5ED", "6ED", "7ED",
  "8ED", "9ED", "AED", "BED", "CED", "DED", "EED", "FED",
  "0FD", "1FD", "2FD", "3FD", "4FD", "5FD", "6FD", "7FD",
  "8FD", "9FD", "AFD", "BFD", "CFD", "DFD", "EFD", "FFD",
  "00E", "10E", "20E", "30E", "40E", "50E", "60E", "70E",
  "80E", "90E", "A0E", "B0E", "C0E", "D0E", "E0E", "F0E",
  "01E", "11E", "21E", "31E", "41E", "51E", "61E", "71E",
  "81E", "91E", "A1E", "B1E", "C1E", "D1E", "E1E", "F1E",
  "02E", "12E", "22E", "32E", "42E", "52E", "62E", "72E",
  "82E", "92E", "A2E", "B2E", "C2E", "D2E", "E2E", "F2E",
  "03E", "13E", "23E", "33E", "43E", "53E", "63E", "73E",
  "83E", "93E", "A3E", "B3E", "C3E", "D3E", "E3E", "F3E",
  "04E", "14E", "24E", "34E", "44E", "54E", "64E", "74E",
  "84E", "94E", "A4E", "B4E", "C4E", "D4E", "E4E", "F4E",
  "05E", "15E", "25E", "35E", "45E", "55E", "65E", "75E",
  "85E", "95E", "A5E", "B5E", "C5E", "D5E", "E5E", "F5E",
  "06E", "16E", "26E", "36E", "46E", "56E", "66E", "76E",
  "86E", "96E", "A6E", "B6E", "C6E", "D6E", "E6E", "F6E",
  "07E", "17E", "27E", "37E", "47E", "57E", "67E", "77E",
  "87E", "97E", "A7E", "B7E", "C7E", "D7E", "E7E", "F7E",
  "08E", "18E", "28E", "38E", "48E", "58E", "68E", "78E",
  "88E", "98E", "A8E", "B8E", "C8E", "D8E", "E8E", "F8E",
  "09E", "19E", "29E", "39E", "49E", "59E", "69E", "79E",
  "89E", "99E", "A9E", "B9E", "C9E", "D9E", "E9E", "F9E",
  "0AE", "1AE", "2AE", "3AE", "4AE", "5AE", "6AE", "7AE",
  "8AE", "9AE", "AAE", "BAE", "CAE", "DAE", "EAE", "FAE",
  "0BE", "1BE", "2BE", "3BE", "4BE", "5BE", "6BE", "7BE",
  "8BE", "9BE", "ABE", "BBE", "CBE", "DBE", "EBE", "FBE",
  "0CE", "1CE", "2CE", "3CE", "4CE", "5CE", "6CE", "7CE",
  "8CE", "9CE", "ACE", "BCE", "CCE", "DCE", "ECE", "FCE",
  "0DE", "1DE", "2DE", "3DE", "4DE", "5DE", "6DE", "7DE",
  "8DE", "9DE", "ADE", "BDE", "CDE", "DDE", "EDE", "FDE",
  "0EE", "1EE", "2EE", "3EE", "4EE", "5EE", "6EE", "7EE",
  "8EE", "9EE", "AEE", "BEE", "CEE", "DEE", "EEE", "FEE",
  "0FE", "1FE", "2FE", "3FE", "4FE", "5FE", "6FE", "7FE",
  "8FE", "9FE", "AFE", "BFE", "CFE", "DFE", "EFE", "FFE",
  "00F", "10F", "20F", "30F", "40F", "50F", "60F", "70F",
  "80F", "90F", "A0F", "B0F", "C0F", "D0F", "E0F", "F0F",
  "01F", "11F", "21F", "31F", "41F", "51F", "61F", "71F",
  "81F", "91F", "A1F", "B1F", "C1F", "D1F", "E1F", "F1F",
  "02F", "12F", "22F", "32F", "42F", "52F", "62F", "72F",
  "82F", "92F", "A2F", "B2F", "C2F", "D2F", "E2F", "F2F",
  "03F", "13F", "23F", "33F", "43F", "53F", "63F", "73F",
  "83F", "93F", "A3F", "B3F", "C3F", "D3F", "E3F", "F3F",
  "04F", "14F", "24F", "34F", "44F", "54F", "64F", "74F",
  "84F", "94F", "A4F", "B4F", "C4F", "D4F", "E4F", "F4F",
  "05F", "15F", "25F", "35F", "45F", "55F", "65F", "75F",
  "85F", "95F", "A5F", "B5F", "C5F", "D5F", "E5F", "F5F",
  "06F", "16F", "26F", "36F", "46F", "56F", "66F", "76F",
  "86F", "96F", "A6F", "B6F", "C6F", "D6F", "E6F", "F6F",
  "07F", "17F", "27F", "37F", "47F", "57F", "67F", "77F",
  "87F", "97F", "A7F", "B7F", "C7F", "D7F", "E7F", "F7F",
  "08F", "18F", "28F", "38F", "48F", "58F", "68F", "78F",
  "88F", "98F", "A8F", "B8F", "C8F", "D8F", "E8F", "F8F",
  "09F", "19F", "29F", "39F", "49F", "59F", "69F", "79F",
  "89F", "99F", "A9F", "B9F", "C9F", "D9F", "E9F", "F9F",
  "0AF", "1AF", "2AF", "3AF", "4AF", "5AF", "6AF", "7AF",
  "8AF", "9AF", "AAF", "BAF", "CAF", "DAF", "EAF", "FAF",
  "0BF", "1BF", "2BF", "3BF", "4BF", "5BF", "6BF", "7BF",
  "8BF", "9BF", "ABF", "BBF", "CBF", "DBF", "EBF", "FBF",
  "0CF", "1CF", "2CF", "3CF", "4CF", "5CF", "6CF", "7CF",
  "8CF", "9CF", "ACF", "BCF", "CCF", "DCF", "ECF", "FCF",
  "0DF", "1DF", "2DF", "3DF", "4DF", "5DF", "6DF", "7DF",
  "8DF", "9DF", "ADF", "BDF", "CDF", "DDF", "EDF", "FDF",
  "0EF", "1EF", "2EF", "3EF", "4EF", "5EF", "6EF", "7EF",
  "8EF", "9EF", "AEF", "BEF", "CEF", "DEF", "EEF", "FEF",
  "0FF", "1FF", "2FF", "3FF", "4FF", "5FF", "6FF", "7FF",
  "8FF", "9FF", "AFF", "BFF", "CFF", "DFF", "EFF", "FFF"
};

/** Append a single character to an output buffer.
 * @param[in,out] buf_p Buffer to append to.
 * @param[in] c Character to append.
 */
static void
addc(struct BufData *buf_p, int c)
{
  int overflow = 0;

  if (buf_p->limit == 0) { /* We've gone past the limit... */
    buf_p->overflow++;
    overflow++;
  } else if (buf_p->limit > 0) /* update the limit */
    buf_p->limit--;

  if (buf_p->buf_loc >= buf_p->buf_size) { /* We've gone past buffer */
    buf_p->buf_overflow++;
    overflow++;
  }

  if (!overflow) /* add the character to the buffer */
    buf_p->buf[buf_p->buf_loc++] = c;
}

/** Append a string to an output buffer.
 * @param[in,out] buf_p Buffer to append to.
 * @param[in] s_len Length of string to append.
 * @param[in] s String to append.
 */
static void
adds(struct BufData *buf_p, int s_len, const char *s)
{
  int overflow = 0;

  /* while the string exists and has non-zero length */
  while (s_len && *s)
  {
    /* poor man's inlining; see addc(), above */
    if (buf_p->limit == 0) { /* We've gone past the limit... */
      buf_p->overflow++;
      overflow++;
    } else if (buf_p->limit > 0) /* update the limit */
      buf_p->limit--;

    if (buf_p->buf_loc >= buf_p->buf_size) { /* We've gone past buffer */
      buf_p->buf_overflow++;
      overflow++;
    }

    if (!overflow) /* add the character to the buffer */
      buf_p->buf[buf_p->buf_loc++] = *s;

    s++; /* advance to next character */
    if (s_len > 0) /* update string length left to copy */
      s_len--;
  }
}

/** Add certain padding to an output buffer.
 * @param[in,out] buf_p Buffer to append to.
 * @param[in] padlen Length of padding to add.
 * @param[in] pad Padding string (at least PAD_LENGTH bytes long).
 */
static void
do_pad(struct BufData *buf_p, int padlen, char *pad)
{
  /* do chunks of PAD_LENGTH first */
  for (; padlen > PAD_LENGTH; padlen -= PAD_LENGTH)
    adds(buf_p, PAD_LENGTH, pad);

  /* add any left-over padding */
  adds(buf_p, padlen, pad);
}

/** Return length of string, up to a maximum.
 * @param[in] str String to find length for.
 * @param[in] maxlen Maximum value to return.
 * @return Minimum of \a maxlen and length of \a str.
 */
static int
my_strnlen(const char *str, int maxlen)
{
  int len = 0;

  while (*str++ && maxlen--)
    len++;

  return len;
}

/** Workhorse printing function.
 * @param[in] dest Client to format the message.
 * @param[in,out] buf_p Description of output buffer.
 * @param[in] fmt Message format string.
 * @param[in] vp Variable-length argument list for format string.
 */
static void
doprintf(struct Client *dest, struct BufData *buf_p, const char *fmt,
	 va_list vp)
{
  enum {
    FLAG,	/* Gathering flags */
    WIDTH,	/* Gathering field width */
    DOT,	/* Found a dot */
    PREC,	/* Gathering field precision */
    OPT,	/* Gathering field options (l, h, q, etc.) */
    SPEC	/* Looking for field specifier */
  } state = FLAG;
  struct FieldData fld_s = FIELDDATA_INIT;
  const char *fstart = 0;

  for (; *fmt; fmt++) {
    /* If it's not %, or if it's %%, append it to the string */
    if (*fmt != '%' || (*fmt == '%' && *++fmt == '%')) {
      addc(buf_p, *fmt); /* add the character to the string */

      continue; /* go to the next character */
    }

    state = FLAG; /* initialize our field data */
    fld_s.flags = 0;
    fld_s.base = BASE_DECIMAL;
    fld_s.width = 0;
    fld_s.prec = -1;
    fstart = fmt;

    for (; *fmt; fmt++) {
      switch (*fmt) {
      case '-': /* Deal with a minus flag */
	if (state == FLAG)
	  fld_s.flags |= FLAG_MINUS;
	else if (state == PREC) { /* precisions may not be negative */
	  fld_s.prec = -1;
	  state = OPT; /* prohibit further precision wrangling */
	}
	continue;

      case '+': /* Deal with a plus flag */
	if (state == FLAG)
	  fld_s.flags |= FLAG_PLUS;
	continue;

      case ' ': /* Deal with a space flag */
	if (state == FLAG)
	  fld_s.flags |= FLAG_SPACE;
	continue;

      case '#': /* Deal with the so-called "alternate" flag */
	if (state == FLAG)
	  fld_s.flags |= FLAG_ALT;
	continue;

      case ':': /* Deal with the colon flag */
	if (state == FLAG)
	  fld_s.flags |= FLAG_COLON;
	continue;

      case '0': /* Deal with a zero flag */
	if (state == FLAG) {
	  fld_s.flags |= FLAG_ZERO;
	  continue;
	}
	/*FALLTHROUGH*/
      case '1':  case '2':  case '3':  case '4':  case '5':
      case '6':  case '7':  case '8':  case '9':
	if (state == FLAG) /* switch to the WIDTH state if needed? */
	  state = WIDTH;
	else if (state != WIDTH && state != PREC)
	  continue; /* don't process it any more */

	/* convert number */
	if (state == WIDTH) {
	  if (fld_s.width < WIDTH_MAX) /* prevent overflow */
	    fld_s.width = fld_s.width * 10 + (*fmt - '0');
	} else {
	  if (fld_s.prec < WIDTH_MAX) /* prevent overflow */
	    fld_s.prec = fld_s.prec * 10 + (*fmt - '0');
	}
	continue;

      case '.': /* We found a '.'; go to precision state */
	if (state <= DOT) {
	  state = PREC;
	  fld_s.prec = 0;
	}
	continue;

      case '*': /* Grab an argument containing a width or precision */
	if (state <= WIDTH && fld_s.width <= 0) {
	  fld_s.width = (short)va_arg(vp, int); /* Get argument */

	  state = DOT; /* '.' better be next */

	  if (fld_s.width < 0) { /* deal with negative width */
	    fld_s.flags |= FLAG_MINUS;
	    fld_s.width = -fld_s.width;
	  }
	} else if (state == PREC && fld_s.prec <= 0) {
	  fld_s.prec = (short)va_arg(vp, int); /* Get argument */

	  state = OPT; /* No more precision stuff */

	  if (fld_s.prec < 0) /* deal with negative precision */
	    fld_s.prec = -1;
	}
	continue;

      case 'h': /* it's a short */
	if (state <= OPT) {
	  state = OPT;
	  if (fld_s.flags & TYPE_SHORT) /* We support 'hh' */
	    fld_s.flags |= TYPE_CHAR;
	  else if (!(fld_s.flags & TYPE_MASK))
	    fld_s.flags |= TYPE_SHORT;
	}
	continue;

      case 'l': /* it's a long */
	if (state <= OPT) {
	  state = OPT;
	  if (fld_s.flags & TYPE_LONG) /* We support 'll' */
	    fld_s.flags |= TYPE_QUAD | TYPE_LONGDOUBLE;
	  else if (!(fld_s.flags & TYPE_MASK))
	    fld_s.flags |= TYPE_LONG;
	}
	continue;

      case 'q':  case 'L': /* it's a quad or long double */
	if (state <= OPT) {
	  state = OPT;
	  if (!(fld_s.flags & TYPE_MASK))
	    fld_s.flags |= TYPE_QUAD | TYPE_LONGDOUBLE;
	}
	continue;

      case 'j': /* it's an intmax_t */
	if (state <= OPT) {
	  state = OPT;
	  if (!(fld_s.flags & TYPE_MASK))
	    fld_s.flags |= TYPE_INTMAX;
	}
	continue;

      case 't': /* it's a ptrdiff_t */
	if (state <= OPT) {
	  state = OPT;
	  if (!(fld_s.flags & TYPE_MASK))
	    fld_s.flags |= TYPE_PTRDIFF;
	}
	continue;

      case 'z':  case 'Z': /* it's a size_t */
	if (state <= OPT) {
	  state = OPT;
	  if (!(fld_s.flags & TYPE_MASK))
	    fld_s.flags |= TYPE_SIZE;
	}
	continue;

      case 'T': /* it's a time_t */
	if (state <= OPT) {
	  state = OPT;
	  if (!(fld_s.flags & TYPE_MASK))
	    fld_s.flags |= TYPE_TIME;
	}
	continue;

      case 's': /* convert a string */
	fld_s.flags &= ~(FLAG_PLUS | FLAG_SPACE | FLAG_ALT | FLAG_ZERO |
			 FLAG_COLON | TYPE_MASK);
	fld_s.flags |= ARG_PTR | CONV_STRING;
	break;

      case 'd':  case 'i':
	fld_s.flags &= ~(FLAG_COLON);
	fld_s.flags |= ARG_INT | CONV_INT;
	break;

      case 'X': /* uppercase hexadecimal */
	fld_s.flags |= INFO_UPPERCASE;
	/*FALLTHROUGH*/
      case 'o':  case 'x': /* octal or hexadecimal */
	if (*fmt == 'o')
	  fld_s.base = BASE_OCTAL;
	else
	  fld_s.base = BASE_HEX;
	/*FALLTHROUGH*/
      case 'u': /* Unsigned int */
	fld_s.flags &= ~(FLAG_PLUS | FLAG_SPACE | FLAG_COLON);
	fld_s.flags |= INFO_UNSIGNED | ARG_INT | CONV_INT;
	break;

	/* Don't support floating point at this time; it's too complicated */
/*        case 'E':  case 'G':  case 'A': */
/*  	fld_s.flags |= INFO_UPPERCASE; */
	/*FALLTHROUGH*/
/*        case 'e':  case 'f':  case 'g':  case 'a': */
/*  	fld_s.flags |= ARG_FLOAT | CONV_FLOAT; */
/*  	break; */

      case 'c': /* character */
	fld_s.flags &= ~(FLAG_PLUS | FLAG_SPACE | FLAG_ALT | FLAG_ZERO |
			 FLAG_COLON | TYPE_MASK);
	fld_s.flags |= INFO_UNSIGNED | ARG_INT | TYPE_CHAR | CONV_CHAR;
	fld_s.prec = -1;
	break;

      case 'p': /* display a pointer */
	fld_s.flags &= ~(FLAG_PLUS | FLAG_SPACE | FLAG_COLON | TYPE_MASK);
	fld_s.flags |= (FLAG_ALT | FLAG_ZERO | TYPE_POINTER | ARG_PTR |
			CONV_INT | INFO_UNSIGNED);
	fld_s.prec = (SIZEOF_VOID_P * 2); /* number of characters */
	fld_s.base = BASE_HEX;
	break;

      case 'n': /* write back a character count */
	if (fld_s.flags & TYPE_CHAR) /* eg, %hhn */
	  *((char *)va_arg(vp, int *)) = TOTAL(buf_p);
	else if (fld_s.flags & TYPE_SHORT) /* eg, %hn */
	  *((short *)va_arg(vp, int *)) = TOTAL(buf_p);
	else if (fld_s.flags & TYPE_QUAD) /* eg, %qn */
	  *((int64_t *)va_arg(vp, int64_t *)) = TOTAL(buf_p);
	else if (fld_s.flags & TYPE_LONG) /* eg, %ln */
	  *((long *)va_arg(vp, long *)) = TOTAL(buf_p);
	else if (fld_s.flags & TYPE_INTMAX) /* eg, %jn */
	  *((_large_t *)va_arg(vp, _large_t *)) = TOTAL(buf_p);
	else if (fld_s.flags & TYPE_PTRDIFF) /* eg, %tn */
	  *((ptrdiff_t *)va_arg(vp, ptrdiff_t *)) = TOTAL(buf_p);
	else if (fld_s.flags & TYPE_SIZE) /* eg, %zn */
	  *((size_t *)va_arg(vp, size_t *)) = TOTAL(buf_p);
	else if (fld_s.flags & TYPE_TIME) /* eg, %Tn */
	  *((time_t *)va_arg(vp, time_t *)) = TOTAL(buf_p);
	else /* eg, %n */
	  *((int *)va_arg(vp, int *)) = TOTAL(buf_p);
	fld_s.flags = 0; /* no further processing required */
	break;

      case 'm': /* write out a string describing an errno error */
	fld_s.flags &= ~(FLAG_PLUS | FLAG_SPACE | FLAG_ALT | FLAG_ZERO |
			 FLAG_COLON | TYPE_MASK);
	fld_s.flags |= CONV_STRING;
	fld_s.value.v_ptr = (void *)strerror(errno);
	break;

      case 'v': /* here's the infamous %v... */
	fld_s.flags &= ~(FLAG_PLUS | FLAG_SPACE | FLAG_ALT | FLAG_ZERO |
			 FLAG_COLON | TYPE_MASK);
	fld_s.flags |= ARG_PTR | CONV_VARARGS;
	break;

      case 'C': /* convert a client name... */
	fld_s.flags &= ~(FLAG_PLUS | FLAG_SPACE | FLAG_ZERO | TYPE_MASK);
	fld_s.flags |= ARG_PTR | CONV_CLIENT;
	break;

      case 'R': /* convert a client name... */
        fld_s.flags &= ~(FLAG_PLUS | FLAG_SPACE | FLAG_ZERO | TYPE_MASK);
        fld_s.flags |= ARG_PTR | CONV_REAL;
        break;

      case 'H': /* convert a channel name... */
	fld_s.flags &= ~(FLAG_PLUS | FLAG_SPACE | FLAG_ALT | FLAG_ZERO |
			 FLAG_COLON | TYPE_MASK);
	fld_s.flags |= ARG_PTR | CONV_CHANNEL;
	break;

      default: /* Unsupported, display a message and the entire format */
	adds(buf_p, -1, "(Unsupported: %");
	adds(buf_p, fmt - fstart + 1, fstart);
	addc(buf_p, ')');
	fld_s.flags = 0; /* no further processing required */
	break;
      } /* switch (*fmt) { */

      break;
    } /* for (; *fmt; fmt++) { */

    if (!*fmt) /* hit the end */
      break;
    else if (!(fld_s.flags & (ARG_MASK | CONV_MASK))) /* is it done? */
      continue;

    if ((fld_s.flags & ARG_MASK) == ARG_INT) { /* grab an integer argument */
      if (fld_s.flags & INFO_UNSIGNED) { /* go direct if unsigned */
	if (fld_s.flags & TYPE_CHAR) /* eg, %hhu */
	  fld_s.value.v_int = (unsigned char)va_arg(vp, unsigned int);
	else if (fld_s.flags & TYPE_SHORT) /* eg, %hu */
	  fld_s.value.v_int = (unsigned short)va_arg(vp, unsigned int);
	else if (fld_s.flags & TYPE_QUAD) /* eg, %qu */
	  fld_s.value.v_int = va_arg(vp, uint64_t);
	else if (fld_s.flags & TYPE_LONG) /* eg, %lu */
	  fld_s.value.v_int = va_arg(vp, unsigned long);
	else if (fld_s.flags & TYPE_INTMAX) /* eg, %ju */
	  fld_s.value.v_int = va_arg(vp, _large_t);
	else if (fld_s.flags & TYPE_PTRDIFF) /* eg, %tu */
	  fld_s.value.v_int = va_arg(vp, ptrdiff_t);
	else if (fld_s.flags & TYPE_SIZE) /* eg, %zu */
	  fld_s.value.v_int = va_arg(vp, size_t);
	else if (fld_s.flags & TYPE_TIME) /* eg, %Tu */
	  fld_s.value.v_int = va_arg(vp, time_t);
	else if (fld_s.flags & TYPE_POINTER) /* eg, %p */
	  fld_s.value.v_int = va_arg(vp, _pointer_t);
	else /* eg, %u */
	  fld_s.value.v_int = va_arg(vp, unsigned int);
      } else {
	_large_t signed_int; /* temp. store the signed integer */

	if (fld_s.flags & TYPE_CHAR) /* eg, %hhd */
	  signed_int = (char)va_arg(vp, unsigned int);
	else if (fld_s.flags & TYPE_SHORT) /* eg, %hd */
	  signed_int = (short)va_arg(vp, unsigned int);
	else if (fld_s.flags & TYPE_QUAD) /* eg, %qd */
	  signed_int = va_arg(vp, int64_t);
	else if (fld_s.flags & TYPE_LONG) /* eg, %ld */
	  signed_int = va_arg(vp, long);
	else if (fld_s.flags & TYPE_INTMAX) /* eg, %jd */
	  signed_int = va_arg(vp, _large_t);
	else if (fld_s.flags & TYPE_PTRDIFF) /* eg, %td */
	  signed_int = va_arg(vp, ptrdiff_t);
	else if (fld_s.flags & TYPE_SIZE) /* eg, %zd */
	  signed_int = va_arg(vp, size_t);
	else if (fld_s.flags & TYPE_TIME) /* eg, %Td */
	  signed_int = va_arg(vp, time_t);
	else /* eg, %d */
	  signed_int = va_arg(vp, int);

	if (signed_int < 0) { /* Now figure out if it's negative... */
	  fld_s.flags |= INFO_NEGATIVE;
	  fld_s.value.v_int = -signed_int; /* negate safely (I hope) */
	} else
	  fld_s.value.v_int = signed_int;
      }
    } else if ((fld_s.flags & ARG_MASK) == ARG_FLOAT) { /* extract a float */
      if (fld_s.flags & TYPE_LONGDOUBLE) /* eg, %Lf */
	fld_s.value.v_float = va_arg(vp, long double);
      else /* eg, %f */
	fld_s.value.v_float = va_arg(vp, double);
    } else if ((fld_s.flags & ARG_MASK) == ARG_PTR) { /* pointer argument */
      fld_s.value.v_ptr = va_arg(vp, void *);
    }

    /* We've eaten the arguments, we have all the information we need for
     * the conversion.  Time to actually *do* the conversion
     */
    if ((fld_s.flags & CONV_MASK) == CONV_INT) {
      /* convert an integer */
      char intbuf[INTBUF_LEN], **table = 0, *tstr;
      int ibuf_loc = INTBUF_LEN, ilen, zlen = 0, plen = 0, elen = 0;

      if (fld_s.base == BASE_OCTAL) /* select string table to use */
	table = octal;
      else if (fld_s.base == BASE_DECIMAL)
	table = decimal;
      else if (fld_s.base == BASE_HEX) { /* have to deal with upper case */
	table = (fld_s.flags & INFO_UPPERCASE) ? HEX : hex;
	if (fld_s.flags & FLAG_ALT)
	  elen = 2; /* account for the length of 0x */
      }

      if (fld_s.prec < 0) { /* default precision is 1 */
	if ((fld_s.flags & (FLAG_MINUS | FLAG_ZERO)) == FLAG_ZERO &&
	    fld_s.width) {
	  fld_s.prec = fld_s.width - elen;
	  fld_s.width = 0;
	} else
	  fld_s.prec = 1;
      }

      /* If there's a sign flag, account for it */
      if (fld_s.flags & (FLAG_PLUS | FLAG_SPACE | INFO_NEGATIVE))
	elen++;

      if (fld_s.base < 0) { /* non-binary base flagged by negative */
	fld_s.base = -fld_s.base; /* negate it... */

	while (fld_s.value.v_int) { /* and convert it */
	  tstr = table[fld_s.value.v_int % fld_s.base]; /* which string? */
	  fld_s.value.v_int /= fld_s.base; /* next value */

	  ilen = 3; /* if we have to fill in zeros, here's how many */

	  while (*tstr) { /* add string to intbuf; note growing backwards */
	    intbuf[--ibuf_loc] = *(tstr++);
	    ilen--;
	  }

	  if (fld_s.value.v_int > 0 && ilen) /* add zeros if needed */
	    while (ilen--)
	      intbuf[--ibuf_loc] = '0';
	}
      } else { /* optimize for powers of 2 */
	while (fld_s.value.v_int) { /* which string? */
	  tstr = table[(fld_s.value.v_int & ((1 << fld_s.base) - 1))];
	  fld_s.value.v_int >>= fld_s.base; /* next value */

	  ilen = 3; /* if we have to fill in zeros, here's how many */

	  while (*tstr) { /* add string to intbuf; note growing backwards */
	    intbuf[--ibuf_loc] = *(tstr++);
	    ilen--;
	  }

	  if (fld_s.value.v_int > 0 && ilen) /* add zeros if needed */
	    while (ilen--)
	      intbuf[--ibuf_loc] = '0';
	}
      }

      ilen = INTBUF_LEN - ibuf_loc; /* how many chars did we add? */

      if (fld_s.prec > ilen) /* do we need any leading zeros? */
	zlen = fld_s.prec - ilen;

      if (fld_s.base == BASE_OCTAL && zlen == 0 && fld_s.flags & FLAG_ALT)
	zlen++; /* factor in a leading zero for %#o */

      if (fld_s.width > ilen + zlen + elen) /* calculate space padding */
	plen = fld_s.width - (ilen + zlen + elen);

      if (plen > 0 && !(fld_s.flags & FLAG_MINUS))
	do_pad(buf_p, plen, spaces); /* pre-padding */

      if (fld_s.flags & INFO_NEGATIVE) /* leading signs */
	addc(buf_p, '-');
      else if (fld_s.flags & FLAG_PLUS)
	addc(buf_p, '+');
      else if (fld_s.flags & FLAG_SPACE)
	addc(buf_p, ' ');

      if ((fld_s.flags & FLAG_ALT) && fld_s.base == BASE_HEX) { /* hex 0x */
	addc(buf_p, '0');
	addc(buf_p, fld_s.flags & INFO_UPPERCASE ? 'X' : 'x');
      }

      if (zlen > 0) /* leading zeros */
	do_pad(buf_p, zlen, zeros);

      adds(buf_p, ilen, intbuf + ibuf_loc); /* add the integer string */

      if (plen > 0 &&  (fld_s.flags & FLAG_MINUS))
	do_pad(buf_p, plen, spaces); /* post-padding */

      /* Don't support floating point at this time; it's too complicated */
/*      } else if ((fld_s.flags & CONV_MASK) == CONV_FLOAT) { */
      /* convert a float */
    } else if ((fld_s.flags & CONV_MASK) == CONV_CHAR) {
      if (fld_s.width > 0 && !(fld_s.flags & FLAG_MINUS))
	do_pad(buf_p, fld_s.width - 1, spaces); /* pre-padding */

      addc(buf_p, fld_s.value.v_int); /* add the character */

      if (fld_s.width > 0 &&  (fld_s.flags & FLAG_MINUS))
	do_pad(buf_p, fld_s.width - 1, spaces); /* post-padding */
    } else if ((fld_s.flags & CONV_MASK) == CONV_STRING ||
	       fld_s.value.v_ptr == 0) { /* spaces or null pointers */
      int slen, plen;
      char *str = (char*) fld_s.value.v_ptr;

      if (!str) /* NULL pointers print "(null)" */
	str = "(null)";

      slen = my_strnlen(str, fld_s.prec); /* str lengths and pad lengths */
      plen = (fld_s.width - slen <= 0 ? 0 : fld_s.width - slen);

      if (plen > 0 && !(fld_s.flags & FLAG_MINUS))
	do_pad(buf_p, plen, spaces); /* pre-padding */

      adds(buf_p, slen, str); /* add the string */

      if (plen > 0 &&  (fld_s.flags & FLAG_MINUS))
	do_pad(buf_p, plen, spaces); /* post-padding */
    } else if ((fld_s.flags & CONV_MASK) == CONV_VARARGS) {
      struct BufData buf_s = BUFDATA_INIT;
      struct VarData *vdata = (struct VarData*) fld_s.value.v_ptr;
      int plen, tlen;

      buf_s.buf = buf_p->buf + buf_p->buf_loc;
      buf_s.buf_size = buf_p->buf_size - buf_p->buf_loc;
      buf_s.limit = fld_s.prec;

      doprintf(dest, &buf_s, vdata->vd_format, vdata->vd_args);

      plen = (fld_s.width - buf_s.buf_loc <= 0 ? 0 :
	      fld_s.width - buf_s.buf_loc);

      if (plen > 0) {
	if (fld_s.flags & FLAG_MINUS) { /* left aligned... */
	  buf_p->buf_loc += buf_s.buf_loc; /* remember the modifications */
	  buf_p->buf_overflow += buf_s.buf_overflow;

	  do_pad(buf_p, plen, spaces); /* and do the post-padding */
	} else { /* right aligned... */
	  /* Ok, first, see if we'll have *anything* left after padding */
	  if (plen > buf_s.buf_size) {
	    /* nope, good, this is easy: everything overflowed buffer */
	    do_pad(buf_p, plen, spaces);

	    buf_s.buf_overflow += buf_s.buf_loc; /* update buf counts */
	    buf_s.buf_loc = 0;
	    buf_p->buf_overflow += buf_s.buf_overflow;
	  } else {
	    /* first figure out how much we're going to save */
	    tlen = SNP_MIN(buf_s.buf_loc, buf_s.buf_size - plen);

	    memmove(buf_s.buf + plen, buf_s.buf, tlen); /* save it... */
	    do_pad(buf_p, plen, spaces); /* add spaces... */

	    buf_s.buf_overflow += buf_s.buf_loc - tlen; /* update buf counts */
	    buf_s.buf_loc = tlen;
	    buf_p->buf_overflow += buf_s.buf_overflow;
	    buf_p->buf_loc += buf_s.buf_loc;
	  }
	}
      } else {
	buf_p->buf_loc += buf_s.buf_loc; /* no padding, but remember mods */
	buf_p->buf_overflow += buf_s.buf_overflow;
      }

      vdata->vd_chars = buf_s.buf_loc; /* return relevant data */
      vdata->vd_overflow = SNP_MAX(buf_s.buf_overflow, buf_s.overflow);
    } else if (((fld_s.flags & CONV_MASK) == CONV_CLIENT) ||
              ((fld_s.flags & CONV_MASK) == CONV_REAL)) {
      struct Client *cptr = (struct Client*) fld_s.value.v_ptr;
      const char *str1 = 0, *str2 = 0, *str3 = 0;
      int slen1 = 0, slen2 = 0, slen3 = 0, elen = 0, plen = 0;

      /* &me is used if it's not a definite server */
      if (dest && (IsServer(dest) || IsMe(dest))) {
	if (IsServer(cptr) || IsMe(cptr))
	  str1 = cli_yxx(cptr);
	else {
	  str1 = cli_yxx(cli_user(cptr)->server);
	  str2 = cli_yxx(cptr);
	}
	fld_s.flags &= ~(FLAG_ALT | FLAG_COLON);
      } else {
	str1 = *cli_name(cptr) ? cli_name(cptr) : "*";
	if (!IsServer(cptr) && !IsMe(cptr) && fld_s.flags & FLAG_ALT) {
	  assert(0 != cli_user(cptr));
	  assert(0 != *(cli_name(cptr)));
          if ((fld_s.flags & CONV_MASK) == CONV_REAL) {
            str2 = cli_user(cptr)->realusername;
            str3 = cli_user(cptr)->realhost;
          } else {
            str2 = cli_user(cptr)->username;
            str3 = cli_user(cptr)->host;
          }
	  str2 = cli_user(cptr)->username;
	  str3 = cli_user(cptr)->host;
	} else
	  fld_s.flags &= ~FLAG_ALT;
      }

      if (fld_s.flags & FLAG_COLON)
	elen++; /* account for : */

      slen1 = my_strnlen(str1, fld_s.prec < 0 ? -1 : fld_s.prec - elen);
      if (fld_s.flags & FLAG_ALT)
	elen++; /* account for ! */
      if (str2 && (fld_s.prec < 0 || fld_s.prec - (slen1 + elen) > 0))
	slen2 = my_strnlen(str2, fld_s.prec < 0 ? -1 : fld_s.prec -
			   (slen1 + elen));
      if (fld_s.flags & FLAG_ALT)
	elen++; /* account for @ */
      if (str3 && (fld_s.prec < 0 || fld_s.prec - (slen1 + slen2 + elen) > 0))
	slen3 = my_strnlen(str3, fld_s.prec < 0 ? -1 : fld_s.prec -
			   (slen1 + slen2 + elen));
      plen = (fld_s.width - (slen1 + slen2 + slen3 + elen) <= 0 ? 0 :
	      fld_s.width - (slen1 + slen2 + slen3 + elen));

      if (plen > 0 && !(fld_s.flags & FLAG_MINUS))
	do_pad(buf_p, plen, spaces); /* pre-padding */

      if (fld_s.flags & FLAG_COLON)
	addc(buf_p, ':');
      adds(buf_p, slen1, str1);
      if (fld_s.flags & FLAG_ALT)
	addc(buf_p, '!');
      if (str2)
	adds(buf_p, slen2, str2);
      if (fld_s.flags & FLAG_ALT)
	addc(buf_p, '@');
      if (str3)
	adds(buf_p, slen3, str3);

      if (plen > 0 &&  (fld_s.flags & FLAG_MINUS))
	do_pad(buf_p, plen, spaces); /* post-padding */
    } else if ((fld_s.flags & CONV_MASK) == CONV_CHANNEL) {
      struct Channel *chan = (struct Channel *)fld_s.value.v_ptr;
      char *str = chan->chname;
      int slen, plen;

      slen = my_strnlen(str, fld_s.prec); /* str lengths and pad lengths */
      plen = (fld_s.width - slen <= 0 ? 0 : fld_s.width - slen);

      if (plen > 0 && !(fld_s.flags & FLAG_MINUS))
	do_pad(buf_p, plen, spaces); /* pre-padding */

      adds(buf_p, slen, str); /* add the string */

      if (plen > 0 &&  (fld_s.flags & FLAG_MINUS))
	do_pad(buf_p, plen, spaces); /* post-padding */
    }
  } /* for (; *fmt; fmt++) { */
}

/* ircd_snprintf() has a big Doxygen comment in the header file. */
int
ircd_snprintf(struct Client *dest, char *buf, size_t buf_len,
	      const char *format, ...)
{
  struct BufData buf_s = BUFDATA_INIT;
  va_list args;

  if (!format)
    return 0;

  buf_s.buf = buf; /* initialize buffer settings */
  buf_s.buf_size = buf_len - 1;
  buf_s.limit = -1;

  va_start(args, format);
  doprintf(dest, &buf_s, format, args); /* fill the buffer */
  va_end(args);

  buf_s.buf[buf_s.buf_loc] = '\0'; /* terminate buffer */

  return TOTAL(&buf_s);
}

/** Like ircd_snprintf() but with a va_list argument list.
 * @param[in] dest Client receiving of message.
 * @param[out] buf Output buffer for formatted message.
 * @param[in] buf_len Number of bytes that can be written to \a buf.
 * @param[in] format Format string for message.
 * @param[in] args Variable-length argument list for format string.
 * @return Number of bytes that would be written to \a buf without truncation.
 */
int
ircd_vsnprintf(struct Client *dest, char *buf, size_t buf_len,
	       const char *format, va_list args)
{
  struct BufData buf_s = BUFDATA_INIT;

  if (!format)
    return 0;

  buf_s.buf = buf; /* initialize buffer settings */
  buf_s.buf_size = buf_len - 1;
  buf_s.limit = -1;

  doprintf(dest, &buf_s, format, args); /* fill the buffer */

  buf_s.buf[buf_s.buf_loc] = '\0'; /* terminate buffer */

  return TOTAL(&buf_s);
}
